阅读 | 去哪儿自动化测试框架Qunit中的零侵入切面技术应用及分布式运行平台

Posted 测试窝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阅读 | 去哪儿自动化测试框架Qunit中的零侵入切面技术应用及分布式运行平台相关的知识,希望对你有一定的参考价值。

作者简介

 


毛京超,任职去哪儿网酒店事业部,负责代理商对接业务线相关的测试工作,参与去哪儿Qunit自动化测试框架的开发。

蒋承君,去哪儿网金融事业部测试工程师,负责金融事业部主系统的测试工作及测试工具研发。本文来自其在“”上的分享。



Qunit简介


Qunit是去哪儿网基于Junit框架自主研发的接口自动化测试框架,目前支持的被测接口协议类型包括:HTTP接口、Dubbo RPC接口和Hessian接口。


该自动化测试框架将常用功能的代码实现(测试数据准备、远程执行SQL、调用被测接口等)封装成一个个标签,测试人员编写自动化测试用例时,只需要按照测试步骤进行规范格式XML文件编写,不必关心具体功能代码的实现,将更多的精力放到自动化测试用例的设计上。


同时Qunit自动化测试框架对接口响应的断言也进行完美的封装,通过将接口响应与基线数据(之前录制的接口响应数据)进行diff的方式进行自动断言,大大提高了自动化测试用例编写的效率。


本次分享的内容是:Qunit自动化测试框架中针对Mock第三方接口数据开发的零侵入切面技术的应用模块和加速自动化用例测试执行速度开发的分布式运行平台模块。


一、零侵入切面技术的应用


1、遇到的问题


大家在编写接口自动化测试用例时必然会涉及到Mock第三方接口数据,遇到以下几个问题应该是家常便饭:


  • 第三方接口数据结构复杂,需要通过查看接口文档、日志和实现代码等手段进行拼接

  • 被测试接口响应结果对第三方接口的数据有很强的依赖,我们编写一个接口的自动化用例需要准备好多份Mock数据用来支持


以上问题的存在,增加了自动化测试用例的编写的时间成本,影响自动化测试用例的编写效率。那么有没有一种方式可以动态的更改第三方数据呢?


下面介绍Qunit自动化测试框架如何引入零侵入切面技术的应用模块来解决这个问题的。


2、解决方案


JavaAgent是拥有修改应用运行代码的一个软件组件。在agent的上下文中,instrumentation提供了重新定义和修改装载在运行时的类(class)的能力。

Qunit自动化化框架基于该技术开发了Catcher agent模块,通过修改CLASS字节码文件实现动态录制和回放第三方接口数据的功能,服务于自动化测试。

该技术方案最大的优点就是不需要对被测系统进行代码修改,即完全无代码入侵的方式实现了对被测系统和第三方模块或构件交互的监视和mock功能。


Catcher agent模块的相关代码也不需要布置到线上环境,和线上生产环境是绝对隔离的,不会造成任何影响。


Catcheragent怎么实现了对第三方接口数据的录制和回放功能呢?下面通过Catcher agent修改CLASS字节码前后的代码对比进行介绍。


修改字节码前:


publicReturnType method(ParamsType[] params) throws Exception{

    //something

}


修改字节码后:


privateReturnType $catcher$method(ParamsType[] params) throws Exception{

    //something

}

publicReturnType method(ParamsType[] params) throws Exception{

    ReturnType returnObj;

    try{

        if(needMock(className, methodName,params)){

            returnObj = mock(className,methodName, params);

        }else{

            returnObj =$catcher$method(params);

        }

    }finally{

        if(needCollect(className, methodName)){

            collect(className, methodName,params, returnObj);

        }

    }

    return returnObj;

}


通过对比可以看出以下几点:


  • Catcher Agent将被测试代码进行重新封装增加相关代码实现

  • 通过needMock函数控制当前应用是使用Mock数据,还是调用真实的接口;

  • 通过needCollect函数控制是否对数据进行录制

  • 需要注意的是collect是异步存储不会对程序运行造成影响


Qunit自动化框架中零侵入切面技术的应用包括录制模式和回放模式两个模式:


  • 录制模式:录制第三方数据,将第三方报文数据保存到本地,用来编写自动化用例使用,可以对录制下来的数据进行参数化配置;

  • 回放模式:使用本地准备好的Mock数据对第三方接口进行Mock,支撑自动化测试。


录制模式:



  


回放模式:



阅读 | 去哪儿自动化测试框架Qunit中的零侵入切面技术应用及分布式运行平台

进行回放模式时,大多数情况下都会对本地存储的第三方测试数据进行参数化,更灵活的应用录制下来的测试数据,因此测试执行时,会先将本地存储的第三方数据和测试用例中配置的变量参数组织成一份完整的测试数据发送给Catcher Agent进行mock第三方接口。


3、Qunit中使用例子


在service中定义catcher切点

进行回放模式时,大多数情况下都会对本地存储的第三方测试数据进行参数化,更灵活的应用录制下来的测试数据,因此测试执行时,会先将本地存储的第三方数据和测试用例中配置的变量参数组织成一份完整的测试数据发送给Catcher Agent进行mock第三方接口。


3、Qunit中使用例子


在service中定义catcher切点


<pointcutid="test-fetchPost"

              serverName="10.10.10.10"

              application="testApp"

              location="com.qunat.test.UpopHttpSender"

              methodName="fetchPost"

              type="CLASS"

              desc="UpopHttpSender.fetchPost()的切面"/>


自动化测试用例中的使用方法


<case>

<catch  pointcut=”test-fetchPost" mock_target="OUTPUT">

{"respCode":"00","respMsg":"成功"}

</catch>

    <callservice="TestCatcher">

      <param name="abc" role="admin"/>

      </call>

       <dataassert />

</case>


执行测试TestCatcher被测接口时,对test-fetchPost第三方接口进行Mock,执行测试时,第三方接口的mock数据为通过传入json格式的赋值,设置respCode=“00”,respMsg=“成功”


录制的测试数据


<#noparse>

{

"respCode":"${respCode}",

"currencyCode":"156",

"validation":"true",

"encoding":"UTF-8",

"bizType":"000301",

"respMsg":"${respMsg}",

"orderId":"170308161349237045589",

"accessType":"0"

}

</#noparse>


录制后的测试数据对respCode和respMsg进行参数化,Qunit编写自动化测试用例时,可以通过json的数据格式对参数化的字段进行重新赋值,使得mock数据使用更灵活。


二、分布式运行平台


1、遇到的问题


随着Qunit自动化测试框架逐步完善,所能支撑的自动化测试场景更加全面,同学们感受到了自动化测试带来的福利,就扩大了自动化测试用例的覆盖,自动化测试用例的场景设计的也越来越复杂,测试用例数量随之暴增,随之测试执行时间的问题就暴露了,原来一次全量用例执行需要10分钟,后来每次自动化测试需要坐等1个小时,测试执行成本增加了。这就是去哪儿网某事业部的使用Qunit自动化框架时遇到的问题。


Qunit的测试执行方式继承了Junit的测试执行方式,通过执行mvn test命令进行单线程执行的,试想如果可以多个线程并行执行测试用例,6个线程并行执行测试,那么10分钟就是执行完毕,测试执行时间成本不就可以降低很多吗?

针对这个问题,我们开发了分布式运行平台模块进行并行执行Qunit的自动化测试用例。


2、解决方案


要并行执行自动化测试用例,需要解决以下问题:


  • 并行执行使用什么策略进行分配测试用例?

  • 并行执行测试用例,测试结果怎么收集到一起?

  • 多个测试用例并行执行,如果测试用例之间有相互影响怎么办?


使用过Junit的同学都知道,Junit的执行原理是先将所有待执行的测试用例加载到内存中,再逐个循环进行执行,最终汇总测试结果生成测试报告。Qunit的执行原理也是这样的,那么我们是否可以对Qunit循环执行测试用例的逻辑进行重写,使其按照我们指定的测试文件进行执行测试呢?是否可以每执行一个测试用例后,就将测试结果实时发送到一个平台中,让平台对其进行汇总展示呢?测试用例之间的相互影响是否可以通过多套独立的测试环境进行解决呢?


在去哪儿网做QA是幸福的,因为公司有个稳定Noah环境管理平台,可以按照自己定义的测试环境模板,动态创建多套独立的测试环境(包括部署被测应用所需的机器、数据库、memeched、redis等),每套测试环境相互对立。


分布式运行平台通过调用Noah环境管理平台的接口创建多套独立的测试环境,按照测试用例文件维度分发测试用例到不同的测试环境中进行执行,并且分发策略参考了每个测试用例文件上次执行时间的长短,优先执行消耗时间最长的测试用例文件,进一步缩短整体测试执行的时间。


下图为分布式运行平台的执行自动化测试用例的流程




分布式运行平台做为去哪儿网统一执行Qunit自动化测试用例的平台,还做调度模板管理、调度任务管理、测试环境管理、测试报告展示、代码覆盖率统计、通过接口调用创建测试任务等功能,用来更友好、更高效的支撑Qunit自动化测试用例执行。


三、总结


零侵入切面技术是使用java agent的技术进行开发,基于这个技术点我们还开发了Catcher系统,可以支持java工程的任何一个类的方法的返回值进行录制和回放,目前已经在功能测试进行试用。


分布式运行平台的核心功能是通过创建多套环境并行执行自动化测试用例及汇总测试结果的方式,达到缩短整体测试执行时间的目的,该平台除支撑Qunit自动化测试用例的执行外,后续会支撑去哪儿网其他自动化测试框架的测试执行,最终成为一个公司级通用的分布式运行平台。

 

下载PPT请戳文章底部“阅读原文”。



推荐阅读:



*作为上海互联网领军企业,携程致力于营造上海的技术交流氛围,为技术圈小伙伴搭建更好的交流沟通平台,共同成长进步。也欢迎有同样想法的小伙伴,来沟通合作,邮件niuq@ctrip.com*


责任编辑 | 狒狒




以上是关于阅读 | 去哪儿自动化测试框架Qunit中的零侵入切面技术应用及分布式运行平台的主要内容,如果未能解决你的问题,请参考以下文章

Qunit零侵入切面技术应用及分布式运行平台

QTest大会Qunit新标签-你值得拥有

30分钟Qunit入门教程

Karma 与测试框架 Jasmine、Mocha、QUnit [关闭]

QUnit 模型、测试和断言命名约定

qunit 前端脚本测试用例