基于Java+HttpClient+TestNG的接口自动化测试框架(一)-------接口测试模型

时间:2024-03-05 22:45:07

  本篇开始,将陆续介绍基于Java+HttpClient+TestNG的接口自动化测试框架。(这里需要阅读的童鞋们有Java的编码知识及HttpClient和TestNG的使用经验。

  首先,我们需要讨论一下,什么是接口测试?为什么要做接口测试?以及我们这个框架解决的问题是什么。

  什么是接口测试?首先需要说明一下什么是接口。按照百度的定义,接口------外部系统与系统之间以及内部各个子系统之间的交互点。这么说有点抽象,简单来说,如果我要在一个网页中显示一些数据/文字什么的,我需要有数据来源,碰巧这些数据来源是需要经过逻辑计算的,又碰巧这些数据来源不是来自同一个服务器。那么,如果我直接把这些逻辑和请求都写在页面上显然是不合适的。这时,我们需要去请求一个接口,这个接口就是页面显示和后台服务之间的交互点。接口测试就是测试这个交互点的功能是否正常,我所需要的数据是否按既定的逻辑进行返回。从这个意义上来说,接口测试非常简单,我们只需要考虑各种输入条件下,会产生相应的什么结果,是最为简单的黑盒测试!

  那么为什么要做接口测试呢?无他,总体来说就是成本低,效果好,速度快。

  在前端的童鞋还没有完成UI页面之前,传统的测试是不太可能进行的。而接口测试不需要UI界面,直接通过接口去验证后台逻辑。而且,如果有人通过抓包,直接跳过前端的校验,去进入后端的程序。也是一件很危险的事情。因此,接口测试可以尽可能早的开展。越早介入测试,发现的问题解决起来的成本是越低的。在传统的测试中,开发没有将完整产品提交给测试时,测试这边是无法工作的。而在现在流行的敏捷开发中,开发可以写完一个接口就进行一轮接口测试的回归,以最小的代价快速保证质量。

  接口测试性价比很高,很多公司也比较喜欢进行接口测试。那么当我们做接口测试时,到底需要做哪些方面的工作呢?

  1. 获取需求文档和接口文档 --------> 实际有可能没有,有可能不全。
  2. 通过对需求文档分析出接口的业务逻辑要求以及业务边界 -------->对测试的业务场景进行构建
  3. 通过对接口文档分析出接口的技术指标(接口地址、请求方式、入参、出参)-------->实际测试的之前必须搞清楚要访问接口的信息。
  4. 接口测试用例设计(着重于接口测试数据准备)-------->业务数据的准备尤为重要。
  5. 使用接口测试工具进行接口测试 --------> 可以使用Jmeter,Postman等软件,也可以使用自动化测试框架
  6. 接口缺陷管理与跟踪 -------->生成测试的log与报告
  7. 接口自动化持续集成 -------->用于Jenkins平台

  在这里,有一个误区,很多人认为会使用接口测试工具就是会接口测试。其实接口测试远远不止是工具的使用,Jmeter也好,Postman也好,这些工具都是我们在进行接口测试过程中能够更方便的进行测试,而工具仅仅是工具,真正核心部分还是接口测试用例设计以及测试思维。

  既然已经有了接口测试的软件,也能一定程序上实现接口测试的自动化操作。为什么我们还要费劲周折的去写接口自动化测试框架呢?说实话,我一开始也不是很明白。直到后来,我遇到了这样一个接口,

这个接口的访问需要输入一个sign作为参数。而这个sign的获取方式如下:

  int A 为当前系统的Unix时间戳。(即1970年1月1日到现在有多少秒),String B为当前用户所对应的secret数据库id(一个32位字符串),String C为当前的appkey(可以通过另外一个接口获得),

将int A转为16进制,然后变成字符串,与B及C拼接成字符串D,然后对字符串D取MD5的值,作为sign。

  说实话,这个我不知道用Jmeter或者Postman怎么做。尤其是int A每一秒都不一样。在这种情况下,自己写个工具来解决,是不是方便很多呢?

       针对一些使用工具进行接口测试的痛点,就说说我们这个接口自动化测试框架能够解决哪些问题。

  1. 采用数据驱动方式来解决大量功能重复性接口的测试。
  2. 针对返回JSON字符串,采用JSONPath的模式来精准判定JSON的内容。
  3. 可以生成比较直观的报告。

  当然,也可以集成很多小工具。比如上面提到的计算MD5的值。

  先开个头,想想一个接口的请求及返回是由哪些构成的呢?

  请求的有:url,访问方法,请求头,body,参数等,返回的有json字符串,状态等。

  我们可以根据接口的访问和返回的内容,做成一个Bean,来记录请求和返回及判定的数据,而这些数据都记录在Excel中。

  现在做成Excel的基础类:

  

package apiTest.bean;

public class baseBean {
    private String excelName;
    private String sheetName;
public String getSheetName() { return sheetName; } public void setSheetName(String sheetName) { this.sheetName = sheetName; } public String getExcelName() { return excelName; } public void setExcelName(String excelName) { this.excelName = excelName; } }

        然后,我们的api请求及返回继承这个基础类。 

package apiTest.bean;

public class apiDataBean extends baseBean {
    private boolean run; //是否运行
    private String desc; // 接口描述
    private String method;//访问方法
    private String url; //接口访问url
    
    //header的情况相对复杂,可以设置公共header,也可以针对个别请求来设定访问的header。
    private String header;
    private String body;//接口请求时的body
    private boolean contains; //是否对返回的json字符串中作包含判定(针对接口返回内容较多,不好具*定路径的情况)
    private int status; //返回状态
    private String verify;//判定内容
    private String save; //需要保存的内容
    private String param; //接口发送需要的参数
    private int sleep; //暂停时间
    public boolean isRun() {
        return run;
    }
    public void setRun(boolean run) {
        this.run = run;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public String getMethod() {
        return method;
    }
    public void setMethod(String method) {
        this.method = method;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getHeader() {
        return header;
    }
    public void setHeader(String header) {
        this.header = header;
    }
    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public boolean isContains() {
        return contains;
    }
    public void setContains(boolean contains) {
        this.contains = contains;
    }
    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
    }
    public String getVerify() {
        return verify;
    }
    public void setVerify(String verify) {
        this.verify = verify;
    }
    public String getSave() {
        return save;
    }
    public void setSave(String save) {
        this.save = save;
    }
    public String getParam() {
        return param;
    }
    public void setParam(String param) {
        this.param = param;
    }
    public int getSleep() {
        return sleep;
    }
    public void setSleep(int sleep) {
        this.sleep = sleep;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return String.format("desc:%s,method:%s,url:%s,param:%s", this.desc,
                this.method, this.url, this.body);
    }
}

 

       好的,这样我们就对接口及返回数据制作了一个类,这个类就是接口测试的数据模型。

  开篇先写道这里。之后我们来讨论配置的读取和设定。