接口自动化测试框架搭建 – Java+TestNG 测试Restful service

接口自动化测试 – Java+TestNG 测试 Restful Web Service

关键词:基于Rest的Web服务,接口自动化测试,数据驱动测试,测试Restful Web Service, 数据分离,Java+Maven+TestNG

本文主要介绍如何用Java针对Restful web service 做接口自动化测试(数据驱动),相比UI自动化,接口自动化稳定性可靠性高,实施难易程度低,做自动化性价比高。所用到的工具或类库有 TestNG, Apache POI, Jayway rest-assured,Skyscreamer - JSONassert

简介:

思想是数据驱动测试,用Excel来管理数据,‘Input’ Sheet中存放输入数据,读取数据后拼成request 调用service, 拿到response后写入 ‘Output’ Sheet 即实际结果, ‘Baseline’为基线(期望结果)用来和实际结果对比的,‘Comparison’ Sheet里存放的是对比结果不一致的记录,‘Result’ Sheet 是一个简单的结果报告。

Maven工程目录结构:

详细介绍

核心就一个测试类HTTPReqGenTest.java 由四部分组成

@BeforeTest  读取Excel (WorkBook) 的 ‘Input’ 和 ‘Baseline’ sheet

并且新建‘Output’, ‘Comparison’, ‘Result’ 三个空sheet

读取http_request_template.txt 内容转成string

@DataProvider (name = "WorkBookData")

TestNG的DataProvider, 首先用DataReader构造函数,读取Excel中Input的数据,放入HashMap<String, RecordHandler>, Map的key值就是test case的ID,value是RecordHandler对象,此对象中一个重要的成员属性就是input sheet里面 column和value 的键值对,遍历Map将test case ID 与 test case的value 即input sheet前两列的值放入List<Object[]> ,最后返回List的迭代器iterator (为了循环调用@Test方法)

@Test (dataProvider = "WorkBookData", description = "ReqGenTest")

测试方法,由DataProvider提供数据,首先根据ID去取myInputData里的RecordHandler, 由它和template 去生成request, 然后执行request 返回response,这些工作都是由HTTPReqGen.java这个类完成的,借助com.jayway.restassured, 返回的response是一个JSON体,通过org.skyscreamer.jsonassert.JSONCompare 与Baseline中事先填好的期望结果(同样也是JSON格式)进行比较, 根据结果是Pass还是Fail, 都会相应的往Excel里的相应Sheet写结果。

@AfterTest

写入统计的一些数据

关闭文件流

实现代码:

HTTPReqGenTest.java

package com.demo.qa.rest_api_test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.json.JSONException;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;
import org.testng.Assert;
import org.testng.ITest;
import org.testng.ITestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import com.demo.qa.utils.DataReader;
import com.demo.qa.utils.DataWriter;
import com.demo.qa.utils.HTTPReqGen;
import com.demo.qa.utils.RecordHandler;
import com.demo.qa.utils.SheetUtils;
import com.demo.qa.utils.Utils;
import com.jayway.restassured.response.Response;

public class HTTPReqGenTest implements ITest {

    private Response response;
    private DataReader myInputData;
    private DataReader myBaselineData;
    private String template;

    public String getTestName() {
        return "API Test";
    }

    String filePath = "";

    XSSFWorkbook wb = null;
    XSSFSheet inputSheet = null;
    XSSFSheet baselineSheet = null;
    XSSFSheet outputSheet = null;
    XSSFSheet comparsionSheet = null;
    XSSFSheet resultSheet = null;

    private double totalcase = 0;
    private double failedcase = 0;
    private String startTime = "";
    private String endTime = "";

    @BeforeTest
    @Parameters("workBook")
    public void setup(String path) {
        filePath = path;
        try {
            wb = new XSSFWorkbook(new FileInputStream(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        inputSheet = wb.getSheet("Input");
        baselineSheet = wb.getSheet("Baseline");

        SheetUtils.removeSheetByName(wb, "Output");
        SheetUtils.removeSheetByName(wb, "Comparison");
        SheetUtils.removeSheetByName(wb, "Result");
        outputSheet = wb.createSheet("Output");
        comparsionSheet = wb.createSheet("Comparison");
        resultSheet = wb.createSheet("Result");

        try {
            InputStream is = HTTPReqGenTest.class.getClassLoader().getResourceAsStream("http_request_template.txt");
            template = IOUtils.toString(is, Charset.defaultCharset());
        } catch (Exception e) {
            Assert.fail("Problem fetching data from input file:" + e.getMessage());
        }

        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        startTime = sf.format(new Date());
    }

    @DataProvider(name = "WorkBookData")
    protected Iterator<Object[]> testProvider(ITestContext context) {

        List<Object[]> test_IDs = new ArrayList<Object[]>();

            myInputData = new DataReader(inputSheet, true, true, 0);
            Map<String, RecordHandler> myInput = myInputData.get_map();

            // sort map in order so that test cases ran in a fixed order
            Map<String, RecordHandler> sortmap = Utils.sortmap(myInput);

            for (Map.Entry<String, RecordHandler> entry : sortmap.entrySet()) {
                String test_ID = entry.getKey();
                String test_case = entry.getValue().get("TestCase");
                if (!test_ID.equals("") && !test_case.equals("")) {
                    test_IDs.add(new Object[] { test_ID, test_case });
                }
                totalcase++;
            }

            myBaselineData = new DataReader(baselineSheet, true, true, 0);

        return test_IDs.iterator();
    }

    @Test(dataProvider = "WorkBookData", description = "ReqGenTest")
    public void api_test(String ID, String test_case) {

        HTTPReqGen myReqGen = new HTTPReqGen();

        try {
            myReqGen.generate_request(template, myInputData.get_record(ID));
            response = myReqGen.perform_request();
        } catch (Exception e) {
            Assert.fail("Problem using HTTPRequestGenerator to generate response: " + e.getMessage());
        }

        String baseline_message = myBaselineData.get_record(ID).get("Response");

        if (response.statusCode() == 200)
            try {
                DataWriter.writeData(outputSheet, response.asString(), ID, test_case);

                JSONCompareResult result = JSONCompare.compareJSON(baseline_message, response.asString(), JSONCompareMode.NON_EXTENSIBLE);
                if (!result.passed()) {
                    DataWriter.writeData(comparsionSheet, result, ID, test_case);
                    DataWriter.writeData(resultSheet, "false", ID, test_case, 0);
                    DataWriter.writeData(outputSheet);
                    failedcase++;
                } else {
                    DataWriter.writeData(resultSheet, "true", ID, test_case, 0);
                }
            } catch (JSONException e) {
                DataWriter.writeData(comparsionSheet, "", "Problem to assert Response and baseline messages: "+e.getMessage(), ID, test_case);
                DataWriter.writeData(resultSheet, "error", ID, test_case, 0);
                failedcase++;
                Assert.fail("Problem to assert Response and baseline messages: " + e.getMessage());
            }
        else {
            DataWriter.writeData(outputSheet, response.statusLine(), ID, test_case);

            if (baseline_message.equals(response.statusLine())) {
                DataWriter.writeData(resultSheet, "true", ID, test_case, 0);
            } else {
                DataWriter.writeData(comparsionSheet, baseline_message, response.statusLine(), ID, test_case);
                DataWriter.writeData(resultSheet, "false", ID, test_case, 0);
                DataWriter.writeData(outputSheet);
                failedcase++;
            }
        }
    }

    @AfterTest
    public void teardown() {
        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        endTime = sf.format(new Date());
        DataWriter.writeData(resultSheet, totalcase, failedcase, startTime, endTime);

        try {
            FileOutputStream fileOutputStream = new FileOutputStream(filePath);
            wb.write(fileOutputStream);
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

DataReader

 

HTTPReqGen

 

RecordHandler

 

其它不重要的类不一一列出来了。

pom.xml

 View pom.xml

运行是通过TestNG的xml文件来执行的, 里面配置了Parameter “workBook” 的路径

TestNG的运行结果都是Pass, 但事实上里面有case是Fail的,我只是借助TestNG来运行,我并没有在@Test方法里加断言Assert, 所以这里不会Fail, 我的目的是完全用Excel来管理维护测试数据以及测试结果,做到数据脚本完全分离。

Output sheet

Comparison sheet

Result sheet

当然 你也可以把maven工程打成一个可执行jar来运行,不过需要增加一个main函数作为入口,xml测试文件通过参数传递进去,另外还需要在pom里配置一些插件,像maven-jar-plugin。

如果你还需要做back-end DB check,你可以在Input里再增加几列,你要查询的表,字段,Baseline里也相应的加上期望结果,这里就不再赘述了。

http://www.cnblogs.com/wade-xu/p/4229805.html

注:转载需注明出处及作者名。

时间: 2025-01-02 16:51:19

接口自动化测试框架搭建 – Java+TestNG 测试Restful service的相关文章

零成本实现接口自动化测试 – Java+TestNG 测试Restful service

本文是转载Wade Xu的文章http://www.cnblogs.com/wade-xu/p/4229805.html 接口自动化测试 – Java+TestNG 测试 Restful Web Service 关键词:基于Rest的Web服务,接口自动化测试,数据驱动测试,测试Restful Web Service, 数据分离,Java+Maven+TestNG 本文主要介绍如何用Java针对Restful web service 做接口自动化测试(数据驱动),相比UI自动化,接口自动化稳定性

(转)接口自动化测试 – Java+TestNG 测试 Restful Web Service

本文主要介绍如何用Java针对Restful web service 做接口自动化测试(数据驱动),相比UI自动化,接口自动化稳定性可靠性高,实施难易程度低,做自动化性价比高.所用到的工具或类库有 TestNG, Apache POI, Jayway rest-assured,Skyscreamer - JSONassert 简介: 思想是数据驱动测试,用Excel来管理数据,‘Input’ Sheet中存放输入数据,读取数据后拼成request 调用service, 拿到response后写入

自动化测试框架selenium+java+TestNG——配置篇

最近来总结下自动化测试 selenium的一些常用框架测试搭配,由简入繁,最简单的就是selenium+java+TestNG了,因为我用的是java,就只是总结下java了. TestNG在线安装: 打开Eclipse   Help ->Install New Software ,   然后Add   "http://beust.com/eclipse" 选择TestNG,finish下一步完成安装. 验证是否安装成功 File->new->other 导入sele

基于Java+HttpClient+TestNG的接口自动化测试框架(五)------ 测试用函数接口类及实现类

在前一篇中,我们着重阐述了参数的处理方法. 但是,这些参数基本都是直接赋值的.而实际的接口测试中,我们会根据需要做成很多的测试数据,这些测试数据会根据不同的情况来使用.例如,我可能需要一个能够随机生成一个中文的字符串,或者需要一个能够迅速求出一个文件或者字符串的MD5的值.在这种情况下,就需要我们动手去写一些函数来进行调用. 不过,如果是在Excel(或者其他文本编辑器)中写测试用例,如何才能让程序能够知道我是在调用一个函数,并且能够把这个函数的返回值赋给变量,正确的传入我想要的地方呢?下面,我

接口自动化测试框架搭建

1.创建一个工程 apiFrame 2.创建目录结构 3.base包,基础的,把公共的底层的代码放在base,如请求方法的封装,协议的封装,消息的封装 4.data,放数据文件,如csv文件.excel.yaml 5.config,请求地址不要放在接口测试模块中,单独出来处理进行自动判断 6.utils包,放工具的类,比如yaml文件 7.log日志的文件夹,放对应的日志 8.report放测试报告 9.所有的测试点放在tests包 10.Readme.md说明,给别人来看代码用 11.requ

接口自动化测试框架 (一) :APIAutoTest框架

前言 随着测试技术的发展,接口自动化测试逐渐成为各大公司投入产出比最高的测试技术.介入时间早,执行效率高,稳定性高的优点,让越来越多的公司引入接口自动化测试. 框架简介 APIAutoTest是处理API接口的轻量级自动化测试框架,Java语言实现,基于TestNG测试框架,支持持续集成,自动构建与测试. 框架介绍 1.    数据驱动设计,使用TestNG中的@DataProvider读取Excel中存储的自动化测试用例. 2.    基于TestNG测试框架 3.    使用HttpClie

【python3+request】python3+requests接口自动化测试框架实例详解教程

转自:https://my.oschina.net/u/3041656/blog/820023 前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接口的自动化框架,使用的是java语言,但对于一个学java,却在学python的我来说,觉得python比起java更简单些,所以,我决定自己写python的接口自动化测试框架,由于本人也是刚学习python,

robot framework + python实现http接口自动化测试框架

https://www.jianshu.com/p/6d1e8cb90e7d 前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了bug,所以需要一遍遍回归case,过程一直手工去执行,苦不堪言.所以,对于即将开始的http接口测试需求,立马花了两天时间搭建了一个http接口自动化测试框架用于测试后期回归测试,实在是被大量的重复手工执行搞怕了. 基础

接口自动化测试框架 :APIAutoTest框架

前言 随着测试技术的发展,接口自动化测试逐渐成为各大公司投入产出比最高的测试技术.介入时间早,执行效率高,稳定性高的优点,让越来越多的公司引入接口自动化测试. 框架简介 APIAutoTest是处理API接口的轻量级自动化测试框架,Java语言实现,基于TestNG测试框架,支持持续集成,自动构建与测试. 框架介绍 1.    数据驱动设计,使用TestNG中的@DataProvider读取Excel中存储的自动化测试用例. 2.    基于TestNG测试框架 3.    使用HttpClie