基于testNG的数据驱动测试的自动化测试实践(一)

历时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"
}

 

 

    

 

 

    

 

你可能感兴趣的:(自动化测试)