手记

根据接口文档中的入参,生成自动化测试用例中的异常测试用例,包含用例描述,用例数据

不想当将军的小兵,不是好的小兵;不想做开发的测试,不是好的测试;

不管你信不信,我是信了...

一直以来,内心总有些迷茫的时候,迷茫的是作为测试既然要学那么多编程,为什么不直接去干开发呢?

看了这句话,才发现自己钻进了牛角尖,没有站在更高的高度来思考测试这个岗位,而仅仅是作为一个测试员,或者说是抱着急功近利的心态在想问题,从而忽略了测试的本质。

测试的本质是尽可能的发现软件的缺陷,更高级的应该是用更少的时间,更少的人员来找出更多的缺陷。那么不管更好的测试流程,更高效的测试方法,更好的测试工具,这些都应该是我们追求的东西。

流程,方法,工具,这三者中我认为更重要的应该是方法,最难提升的也是方法。

编码啊工具之类的可以用到哪些提升哪些,

说到底,不管是开发中的编码,还是测试中的编码,都是很初级的工作,都不是这个职业链中的高端,高端应该是对设计对方法的研究与创新,甚至引发自己所处职业的一种潮流。

做好测试不是靠编程,而是靠的是严禁的作风,慎密的逻辑思维,适合的测试流程。从用户角度,到系统角度,到黑产角度,既保证给普通用户很好的用户体验,也保证系统运行平顺流畅,也保证不能应为hacker的攻击而功亏一篑

 

 

进入正题,最近在研究API接口中,异常测试用例的自动化问题,这边考虑的自动化,是通过接口说明文档,自动生成用例描述,用例的入参数据,用例的断言数据,当然测试的级别不是最高的,可以设置为2左右

比如一个注册接口,异常的测试用例,是不是需要判断,每一个必传入参是否传入,那这边就有2N条测试用例

1.请求传入的必传参数var1未传,验证返回var1....

2. 请求传入的必传参数var1传入的为空字符串(String类型)/null(..), 验证返回var1.....

异常测试用例还需要判断入参的长度,是不是又有了

3. 请求传入的参数var1超过最大长度限制,验证返回var1

有些入参有要求,比如用list,异常测试用例又有了 

4.请求传入的参数Var1不是xx类型,验证返回

入参最好还需要判断是否将入参首位的空格去掉,异常测试用例又有了 

5. 请求传入的入参首尾含有空格,验证存入DB中不含空格【要求代码对入参的首尾空格做trim()操作】

对接口的异常测试用例,弥漫着满满的套路气息,每次都进行编写测试用例,创建测试用例数据和断言等操作,入参多的时候,还是很费时间的,不利于提升工作效率。

更好的办法是:编写代码,自动生成测试用例描述,组装测试用例的数据,自动生成断言等

以前,我们一直用Jmeter创建的脚本来自动生成上述内容,

Jmeter生成jmx脚本,脚本中指定了入参个数、类型,长度等,之后生成用例描述,用例数据和断言

好处就是复用方便,更改下url直接测试

缺点就是,不利于动态生成用例,入参变化多了之后要重新创建新的脚本

还有一个缺点就是low,你若是说你用Jmeter做接口自动化测试的,大厂中厂都会嫌弃你low,因为人家是用Python做的,Java做的。

【low不low!!who cares?!!不是一样能完成任务吗,不一样能持续化集成并发送测试报告吗?你们一个组就100多号测试,也不就是完成这写接口的自动化测试吗,我们刚上手的实习生分分钟都能讲API测试用到飞】

感觉中国人,很喜欢用工具和方式来judge others,我们兄弟公司的人,大多是麻省理工学院的,api测试自动化还是用postman实现的呢,ui测试也只不过是protractor+jasmine等,人家不是low,够用就好,有时候已经不提倡测试,直接leader 做code review

 

现在动态实现接口异常测试用例的生成,用一个简单的例子

 我们常见的接口说明文档,是不是长这样?

 

我页面还没开发完,大意就是讲入参,和比天性,类型,最大长度,等信息填入表中。

 

?

CREATE TABLE [DBO].[QA_APIVAR](    

[APIVAR_ID] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY,    

[API_ID] [INT] NOT NULL,     

[APIVAR_NAME] [VARCHAR](100) NULL,    

[APIVAR_INPUTFLAG] [BIT] NOT NULL DEFAULT 1,    

[APIVAR_INPUTDATATYPE] [VARCHAR](100) NULL,    

[APIVAR_INPUTDATATYPEID] INT NOT NULL,       

[APIVAR_INPUTLENGTH] INT NOT NULL,    

[APIVAR_INPUTSCOPE] [VARCHAR](100) NULL,     

[APIVAR_INPUTNOTE] [VARCHAR](200) NULL,     

[APIVAR_DELETED_FLAG] [BIT] NOT NULL DEFAULT 0,    

[APIVAR_CREATEDT] DATETIME NOT NULL,    

[APIVAR_UPDATEDT] DATETIME NOT NULL)

 

 

 代码单元测试部分,判断必传入参的未传,生成测试用例描述,测试数据body【这边以json格式为sample】,断言暂未写

?

package com.example.demo.api; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping; import java.util.List;import java.util.Random;  @Controllerpublic class ApiVar2Case {      String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";     @Autowired    private ApiVarService apiVarService;      @Autowired    private ApiCaseService apiCaseService;     @RequestMapping("/CheckMustVar")    //根据必传参数,依次生成"请求传入的xx参数未传,验证返回"    public void CheckMustVar() {        List<ApiVarBean> list = apiVarService.CheckMustVar(1);        System.out.println(list);        System.out.println(list.size());        int max = 0;        String body = null;        for (int i = 0; i < list.size(); i++) {            String var = list.get(i).getVal();            var = "请求中未传入" + var + "验证返回" + var + "~~更多断言";            System.out.println(var);            StringBuffer sb = new StringBuffer();            body = "{ \n";            for (int j = 0; j < list.size(); j++) {                 if (list.get(i).getVal() != list.get(j).getVal()) {                    Random random = new Random();                    max = list.get(j).getInputLenght();                    sb = new StringBuffer("");                    for (int k = 0; k < max; k++) {                         sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));                    }                     body = body + "\"" + list.get(j).getVal() + "\":\"" + sb + "\", \n";                  }            }            body = body.substring(0, (body.length() - 3)) + " \n }";            System.out.println(body);            ApiCaseBean apiCaseBean = new ApiCaseBean();            apiCaseBean.setApiCase_taskid(1);            apiCaseBean.setApiCase_name(var);            apiCaseBean.setApiCase_body(body);            apiCaseBean.setApiCase_asseertion(null);            apiCaseBean.setApiCase_priorityid(3);             int count = apiCaseService.save(apiCaseBean);            System.out.println(count);        }    }     //根据必传参数,依次生成"请求传入的XX参数为空字符串"    @RequestMapping("/CheckMustVarEmpty")    public void CheckMustVarEmpty() {        List<ApiVarBean> list = apiVarService.CheckMustVar(1);        int max = 0;        String body = null;        for (int i = 0; i < list.size(); i++) {            String var = list.get(i).getVal();            var = "请求中传入" + var + "为空字符串验证返回" + var + "~~更多断言";            System.out.println(var);            StringBuffer sb = new StringBuffer();            body = "{ \n";            for (int j = 0; j < list.size(); j++) {                 if (list.get(i).getVal() != list.get(j).getVal()) {                    Random random = new Random();                    max = list.get(j).getInputLenght();                    sb = new StringBuffer("");                    for (int k = 0; k < max; k++) {                         sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));                    }                     body = body + "\"" + list.get(j).getVal() + "\":\"" + sb + "\", \n";                  } else {                    body = body + "\"" + list.get(j).getVal() + "\":\"" + "\", \n";                }            }            body = body.substring(0, (body.length() - 3)) + " \n }";            ApiCaseBean apiCaseBean = new ApiCaseBean();            apiCaseBean.setApiCase_taskid(1);            apiCaseBean.setApiCase_name(var);            apiCaseBean.setApiCase_body(body);            apiCaseBean.setApiCase_asseertion(null);            apiCaseBean.setApiCase_priorityid(3);             int count = apiCaseService.save(apiCaseBean);            System.out.println(count);        }    }      //根据接口中参数,依次生成"请求传入的XX参数为最大长度+1,即超过最大长度"    @RequestMapping("/CheckVarOverLength")    public void CheckVarOverLength() {        List<ApiVarBean> list = apiVarService.CheckMustVar(1);        int max = 0;        String body = null;        for (int i = 0; i < list.size(); i++) {            String var = list.get(i).getVal();            int length = list.get(i).getInputLenght();            var = "请求中传入" + var + "的长度为" + length + "实际传入的长度为" + (length + 1) + "验证返回" + var + "~~更多断言";            System.out.println(var);            StringBuffer sb = new StringBuffer();            body = "{ \n";            for (int j = 0; j < list.size(); j++) {                Random random = new Random();                max = list.get(j).getInputLenght();                sb = new StringBuffer("");                if (list.get(i).getVal() != list.get(j).getVal()) {                    for (int k = 0; k < max; k++) {                        sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));                    }                } else {                    for (int k = 0; k <= max; k++) {                        sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));                    }                }                body = body + "\"" + list.get(j).getVal() + "\":\"" + sb + "\", \n";            }            body = body.substring(0, (body.length() - 3)) + " \n }";            ApiCaseBean apiCaseBean = new ApiCaseBean();            apiCaseBean.setApiCase_taskid(1);            apiCaseBean.setApiCase_name(var);            apiCaseBean.setApiCase_body(body);            apiCaseBean.setApiCase_asseertion(null);            apiCaseBean.setApiCase_priorityid(3);             int count = apiCaseService.save(apiCaseBean);            System.out.println(count);        }     }  }  

 

?

1

以下是生成的数据,我当然可以用个对象来接收,并存到数据库中去

 

[ApiCaseBean{num=1, val='name', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=5, InputNote='null'}, ApiCaseBean{num=2, val='ID', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=5, InputNote='null'}, ApiCaseBean{num=3, val='mobile', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=5, InputNote='null'}, ApiCaseBean{num=6, val='apple', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=6, InputNote='null'}, ApiCaseBean{num=7, val='orange', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=6, InputNote='null'}, ApiCaseBean{num=8, val='pear', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=6, InputNote='null'}]
6
请求中未传入name验证返回name~~更多断言
{
"ID":"zHUX3",
"mobile":"0J9jR",
"apple":"BTOfiV",
"orange":"ZUz1DB",
"pear":"8vHDVB"}
请求中未传入ID验证返回ID~~更多断言
{
"name":"8gJfa",
"mobile":"5pKjY",
"apple":"7vZVSJ",
"orange":"45cTEN",
"pear":"v9FliS"}
请求中未传入mobile验证返回mobile~~更多断言
{
"name":"Bi5Xm",
"ID":"OmYSR",
"apple":"IEYHCO",
"orange":"1zPaB6",
"pear":"Jw0d84"}
请求中未传入apple验证返回apple~~更多断言
{
"name":"gesB1",
"ID":"fSCeE",
"mobile":"HmY6j",
"orange":"SKInay",
"pear":"kDeurf"}
请求中未传入orange验证返回orange~~更多断言
{
"name":"KnSwW",
"ID":"9VKd2",
"mobile":"thAXp",
"apple":"apjji8",
"pear":"J3UkLR"}
请求中未传入pear验证返回pear~~更多断言
{
"name":"OTKPo",
"ID":"5WgEh",
"mobile":"gfJZA",
"apple":"aXksSk",
"orange":"JCCGZp"}

 

生成测试用例的表

 

?

CREATE TABLE [DBO].[QA_APICASE](    

[APICASE_ID] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY,    

[API_ID] [INT] NOT NULL,     

[APICASE_NAME] [VARCHAR](100) NULL,    

[APICASE_BODY] [NVARCHAR](2000) NULL,    

[APICASE_ASSERCTION] [VARCHAR](100) NULL,     

[APICASE_PRIORITYID] INT ,    

[APICASE_PASSID] INT,    

[APICASE_DELETED_FLAG] [BIT] NOT NULL DEFAULT 0,    

[APICASE_MEMO] [NVARCHAR](2000) NULL,    

[APICASE_CREATEDT] DATETIME NOT NULL,    

[APICASE_UPDATEDT] DATETIME NOT NULL) 

 

 有了用例描述和数据后,不管用什么接口测试工具,还是自已用Java/Python写的框架,导入数据即可

比如 https://www.cnblogs.com/qianjinyan/p/9951465.html

作者:夏天里的Jasmine

原文出处:https://www.cnblogs.com/qianjinyan/p/10408083.html  

0人推荐
随时随地看视频
慕课网APP