大家好,我是来自京东的陈磊,我今天演讲的题目是《智能化测试探索》,今天的演讲主要从两个方面阐述,先说一下自动化测试现在的现状,然后会详细讲一下我们在智能化测试上的探索。
首先,要讲一下自动化测试的现状,我相信绝大部分公司都是这样。
手工测试工程师做 case 然后测试开发工程师依据测试 case 编写脚本,撰写测试数据,调试测试脚本,然后是提交测试脚本,自动化测试就被迫到了回归测试阶段,自动化测试永远也赶不上 RD 的开发进度。我们团队也有这样的状况存在,这里介绍一下我们部门的一些背景,我们部门的被测系统是中台系统,重点是接口测试,我们的被测接口绝大部分都是京东内部的 RPC 服务协议 JSF 。在我们的团队里,测试工程师每天要花费大量的时间编写测试脚本脚本,因此我们在想,如果可以想办法提高测试脚本的编写速度,就可以提高整个团队的工程生产力,提高 ROI ,因此我们就着手通过一些方法解决测试脚本的问题。我们设计了测试脚本自动生成算法,来用程序完成测试脚本撰写的问题。
我们设计了一种数据结构,就是这样页所示,我们采用一个类二叉树的结构存储函数以及其入参的嵌套关系,一个树节点中包含了名字、类型、左孩子指针,右孩子指针和父亲指针。下面用一个例子来详细介绍一下这个二叉树是如何产生的。其中被测接口是 SetPersion ,其中入参有一个复杂参数 household ,户口类 HouseHold 入如这一页所示。那么通过我们的自动生成算法就会形成如下的一棵树,其中根节点存储的是被测接口的信息,根节点的做左孩子指向第一个基本类型变量节点 sName ,被测接口的第二个入参还是一个基本类型节点,因此 sName 节点的左孩子指向 iAge 节点。下面我们看到被测接口的入参是一个复杂参数,因此根节点的右孩子指向一个 household 节点,然后可以看到 HouseHold 类包含了两个基本类型,因此 household 节点左孩子指向 HouseHold 类的第一个基本类型节点是 sAddress , sAddress 节点左孩子指向 HouseHold 类的第二个基本类型节点 sType 。然后我们通过深度优先遍历,按照我们自己的接 口测试编码规范生成了基于 TestNG 的测试脚本。同时,也生成了一个参数嵌套关系的 Json 文件。
解决的脚本问题,我们就信心满满的开始大力推行接口测试,我们发现测试效率没有太明显的提升,我们发现被测接口有时候变动很大,每次在开始一个测试后,等待全部选中脚本都执行完后,查看报告才发现很多被测接口发生了变成,这无疑浪费了很多时间。因此我们有一次陷入了问题当中。这次我们要解决被测接口变更测试脚本没有及时迭代的问题,我们设计并开发了运行变动检测算法,这里我们借鉴了 Git 的思想。首先我们会给我们第一次生成的脚本和参数嵌套关系 Json 文件执行一次 MD5 ,在服务端执行测试的时候,首先依据被测接口再次执行一次上述的测试脚本自动生成算法,然后也会计算 MD5 。然后我们会分别比对各自的 MD5 值是否一致,如果都一直那么执行测试;如果参数嵌套关系的 Json 文件的 MD5 不一致,通过邮件通知脚本的 Owner ,需要人工介入,如果测试脚本不一致,那么新生成脚本替换老脚本后,执行测试。
就如同茹老师讲述的内容一项,自动化除了脚本还有数据,我们有一个 TDS 测试数据服务中心,他提供三种类型的数据来源,一种是模糊数据,我们直接引入了 fuzzdb 的开源项目,第二个是数据实体,我们才考了 facebook 开源的 mimesis ,在内部对我们内部的所有数据实体进行了抽象,例如我们有一个 Person 的数据实体,它有姓、名、配送地址、银行账号、 username 等等一系列属性,通过一个 generator 生成数据提供给 TDS 使用。还有一种数据来源是智能化的数据,主要是通过在线上环境的服务端加入拦截器,通过拦截器将一些拦截脱敏后存入大数据平台,然后通过一些聚类算法对数据进行训练,对一些抽取聚类中心的数据提供给 TDS 使用。做到这里我们就像既然数据有了,脚本有了那么是不是可以让脚本自己去 TDS 里面获取数据。因此我们设计了一种交互语言 Hil , Hil 是一种测试脚本和 TDS 的契约,是服务和服务间契约的达成载体和实现方式。 Hil 有两种语法,一种是无约束的举个例子,我想选一个人,这是他的姓名,地址,通过如下语句解析出来下面的数据,返回结果是随意给一条;另外一种是有约束的,我通过这条语句拿十条数据, TDS 会按照要求返给我 10 条满足约束的数据。脚本就可以通过 Hil 和 TDS 达成数据契约,告诉 TDS 我需要什么样的数据,这就成了脚本和 TDS 的交互通道。
我们还设计了自动重跑机制,每次测试完成后,会读取代码覆盖报告,要获取代码的覆盖率报告,我们使用的是 Jacoco ,然后提取覆盖率小于预期的被测接口,分析未覆盖条件所需的参数,生成 Hil 语言,发送给 TDS 。 TDS 生成数据存储到对应测试脚本的参数池中,再次执行测试,就这样循环直到覆盖率达到预期或者没有新的 Hil 语句生成。
整个执行流程大体是这样的,我们有一个 CI 系统是全部上述流程的总入口,这个 CI 系统满足调用的 API ,按构建调取,按周期调取,按需调取等持续集成需求。 CI 系统会按需求调取脚本自动生成,然后通过 Hil 让 TDS 会产生一条数据,这条数据我们也不知道是什么,但是它会按照预设好的语义产生一条数据去测试,然后先检测一下这个被测的脚本和接口有没有变,如果没有变化就执行,如果变化了就再次生成一个脚本。然后就开始进入上面的自动重跑机制,测试完成后会产生一份接口测试报告和最终的代码覆盖报告,通过聚合的方式推送到聚合报告系统的,目前整个项目还在内部调试的过程中,目前来说还有一些收益,能省掉一些人工,但是目前还并不完全。我的演讲就到这里,谢谢大家。
提问:我想请教一个问题,刚才讲通过智能化的测试,我没听懂你的调研怎么做的,怎么通过测试保证程序的正确性,这块是怎么保证的?
陈磊:其实结果的检测保证它没有问题是因为我们已经采取了单元测试的思想,保证一些代码的覆盖,覆盖到以后,它就不会出现错误的信息流向,因此可以保证被测系统的质量。
提问:按我的理解,即便是达到覆盖,走了分支,但是并不代表这个程序就是正确的对吧?
陈磊:目前被测还是 Single API 的脚本,对流程化的和强上下文的目前还没有进一步研究。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。