历时4个月,从搭建测试框架到给全员培训,再到最终团队内落地,最终效果是整个团队QA测试阶段效率提升60%多。既然有数据就有衡量标准,统计了近2个月的开发阶段/测试阶段的耗时比,比如自动化前,开发阶段/测试阶段耗时比2:1,如今达到5.3:1,简单说开发5人天,测试原来花费2.5人天,现在花费1人天,当然这是平均值。这不仅是单单自动化测试框架的搭建,还需要配合管理手段,如何将自动化测试不单单用于回归测试而是整个QA测试,何时写用例?何时写脚本?何时执行脚本?如何维护脚本?如何给全员培训?(大家代码基础很薄弱,降低学习成本,快速上手很关键)这一整套的配合才能更好的将自动化测试落地。
整个自动化测试框架搭建经历了2个阶段。
第一个阶段:从0到1,提高效率,耗时3个月,主要目标是框架分层以及70多个API接口的几百个场景的覆盖,效果就是上面提到效率提高60%
第二个阶段:核心框架重构和API接口迁移,耗时1个月,主要目标是降低维护和学习成本,通过1,2次培训,可以上手做自动化测试。同时将被测的API接口迁移至新的框架,最终代码量降低了90%,脚本执行时间提高了95%。
把自动化测试框架比喻成搭积木吧,核心框架的搭建,工具类的封装类似于积木块,按照一定规则写符合各业务需求的用例脚本类似于搭积木,搭积木学习成本较低,只要培训就能上手,按照工具类的方法正确使用,按照框架的层级要求正确拼装,可以使整个团队内自动化测试快速落地。
分层大致是 java--base包 作用:获取接口信息并调用接口,ps:具体的接口地址,名称,基础入参存储于数据库里
--driver包 作用:工具类和selenium驱动,包含入参关键词,接口断言,数据库操作等
--operation包 作用:基于 web driver的UI自动化基础操作
以上部分由专人维护,根据业务需要不断补充接口和工具类
test--autocase包--bvt 作用:冒烟测试范围的用例脚本,用于回归测试
--api 作用:所有功能测试的用例脚本,用于日常功能测试
这一部分由业务测试人员维护,根据各自负责的需求编写对应的测试脚本,90%以上覆盖手工用例。
对于业务人员如何写脚本呢?以一个BVT级别的脚本为例,测试发红包-抢红包-退红包的场景,整个流程需要6个接口。
脚本分为6步:发红包-发红包查询-抢红包-抢红包查询-退红包-退红包查询。
发红包分为绑卡支付,余额支付2种,退款红包又分为原路退回和退回到余额。针对不同的场景,进行组合,会有4种场景,而脚本的流程是相同的,采用testNG的DataProvider可以参数化,只需要增加测试数据,每个测试数据对应一个用例,随着用例的增加不会显性增加代码数量,大多情况下只需要维护好数据即可。
为了更加清晰,测试数据分为3部分{ 用例名称,入参,断言},当然这是比较标准的情况,根据实际接口可以灵活变通。最后脚本如下:
@DataProvider(name = "redpacket_bvt")
public Object[][] redpacket_bvt_parm(){
return new Object[][]{
{"*发红包-绑卡,抢红包,原路退回**","BINDCARD","OLDWAY","{'code':'QM000000','message':'受理成功'}"},
{"*发红包-绑卡,抢红包,退回余额**","BINDCARD","BALANCE","{'code':'QM000000','message':'受理成功'}"},
{"*发红包-余额支付,抢红包,原路退回**","BALANCE","OLDWAY","{'code':'QM000000','message':'受理成功'}"},
{"*发红包-余额支付,抢红包,退回余额**","BALANCE","BALANCE","{'code':'QM000000','message':'受理成功'}"},
};
}
/**
* 发红包-抢红包-退红包
* @throws Exception
*/
@Test(dataProvider ="redpacket_bvt" )
public void redpacket_bvt(String name,String payTool,String refundWay,String assertjson) throws Exception{
System.out.println(name);
//发红包
String replacejsonA="{'orderAmount':'0.02','merchantUserId':'"+huiyuanA+"','payTool':'"+payTool+"','bindId':'"+A_bindid+"'}";
String resultA = YopApiRedpacket.redpacket_consume(merchant,replacejsonA);
ToolUtils.AssertEqualfromJson(resultA, assertjson);
ToolUtils.AssertExist(resultA, "requestNo,redOrderNo,orderAmount");
TimeUnit.SECONDS.sleep(2);
//发红包查询
String replacejsonB="{'sendRequestNo':'"+ToolUtils.getJsonValue(resultA, "requestNo")+"'}";
String resultB = YopApiRedpacket.redpacket_order_query(merchant,replacejsonB);
ToolUtils.AssertEqualfromJson(resultB, assertjson);
ToolUtils.AssertExist(resultB, "total,trxTime,effectiveTime,redOrderNo,state,fromUserNo,lastAmount");
//抢红包
String replacejsonC = "{'trxAmount':'0.01','merchantUserId':'"+huiyuanA+"','redOrderNo':'"+ToolUtils.getJsonValue(resultB, "redOrderNo")+"'}";
String resultC = YopApiRedpacket.redpacket_grab(merchant,replacejsonC);
ToolUtils.AssertEqualfromJson(resultC, assertjson);
ToolUtils.AssertExist(resultC, "requestNo,redOrderNo,grabOrderNo");
//抢红包查询
String replacejsonD = "{'grabRequestNo':'"+ToolUtils.getJsonValue(resultC, "requestNo")+"'}";
String resultD = YopApiRedpacket.redpacket_grab_query(merchant,replacejsonD);
ToolUtils.AssertEqualfromJson(resultD, assertjson);
ToolUtils.AssertExist(resultD, "requestNo,redOrderNo,grabOrderNo,amount,ppMerchantNo,toUserNo,status,grabTime");
//退红包
String replacejsonE = "{'redOrderNo':'"+ToolUtils.getJsonValue(resultC, "redOrderNo") +"','refundWay':'"+refundWay+"'}";
String resultE = YopApiRedpacket.redpacket_refund(merchant, replacejsonE);
ToolUtils.AssertEqualfromJson(resultE, assertjson);
ToolUtils.AssertExist(resultE, "requestNo,redOrderNo,refundAmount");
TimeUnit.SECONDS.sleep(2);
String replacejsonF = "{'redOrderNo':'"+ToolUtils.getJsonValue(resultE, "redOrderNo")+"'}";
String resultF = YopApiRedpacket.redpacket_refund_query(merchant, replacejsonF);
ToolUtils.AssertEqualfromJson(resultF, assertjson);
ToolUtils.AssertExist(resultF, "requestNo,redOrderNo,refundWay,ppMerchantNo,refundAmount,merchantUserId,status,createTime,updateTime,refundTime");
}
1、保存一组基础入参,比如一个接口有5个字段,3个必填项,2个非必填。那么3个必填项是基础入参,存在数据库里,2个非必填根据用例需要在业务层测试数据传入。
2、无论是不是必填项,根据用例场景需要变化的入参在业务层传入,没有传入的取自数据库的基础入参,这样可以减少测试数据的维护成本。
3、定义一些关键词,比如随机数,当前日期等等,看业务需要,作用就不多说了,做过自动化基本都知道。
关键词 | 含义 | 示例 |
---|---|---|
@random | 随机字符串10位 | txt@random = txt1234567890 |
@date | 当前时间 | @date = yyyy-MM-dd HH:mm:ss |
@merchant | 所选测试钱麦商编,如1247 | @merchant = BM12345678901247 |
4、入参格式:统一json形式传递。
{
"requestNo":"redf@random",
"orderAmount":"0.02",
"merchantOrderDate":"@date",
"merchantExpireTime":"",
"serverCallbackUrl":"@serverCallbackUrl",
"merchantUserId":"qianmai3610",
"payTool":"BINDCARD",
"totalNumber":"2",
"bindId":"262531657",
"userIp":"10.1.1.1"
}