更多的注入类型——阿里测试之道(12)

发表于:2022-4-26 09:33

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:阿里巴巴技术质量小组    来源:51Testing软件测试网原创

  1.6.3更多的注入类型
  1.线下质量红蓝攻防
  变异测试不仅可以用来度量自动化测试用例的有效性,也可以用来度量整个研发流程中所有质量保障手段的总体有效性。例如,如果我们的代码里面有一个Bug,那么发现Bug的手段可以是代码评审,可以是代码扫描,可以是单元测试接口测试,可以是自动化的全链路回归测试,也可以是手动的探索性测试(ExploratoryTest)。
  用变异测试来度量整个研发流程的质量保障能力,我们称之为线下质量红蓝攻防。具体的做法是:
  (1)准备。蓝军(攻方)的准备工作有:制定注入的策略(范围、频次、类型等)、制定评分规则、维护pr工具以及服务端的配套能力(例如跟踪变异的修复情况)、落实技术方案,确保变异不被发布到线上。
  红军(守方)的准备工作:无。红军要做的就是像平时一样工作。
  (2)注入。蓝军会在开发人员提交代码的时候注入变异。注入是自动的,无须蓝军人工操作。我们修改了用于提交pullrequest的客户端工具pr,pr会自动选择一部分代码提交,在正常的提交过程中“神不知鬼不觉”地修改代码并注入变异。
  之前不含注入的代码提交流程是:
  工程师老王在本地修改了abc.java。
  老王执行gitadd和gitcommit。
  老王执行pr命令。
  pr命令创建远程临时分支,把本地分支gitpush到远程临时分支,然后提交pullrequest。
  代码门禁执行完成,pullrequest合并,代码进入迭代分支。
  带变异注入的代码提交流程是:
  工程师老王在本地修改了abc.java。
  老王执行gitadd和gitcommit。
  老王执行pr命令。pr命令在后台修改abc.java、注入变异,并执行gitcommit--amend--no-edit。
  pr命令创建远程临时分支,把本地分支gitpush到远程临时分支,然后提交pullrequest。
  代码门禁执行完成,pullrequest合并,代码进入迭代分支。
  pullrequest像往常一样被正常创建了,但是提交的代码已经被“篡改”了,即完成了一次注入变异(例如,>被改成了>=)。pr命令会把这次注入的情况回传到服务端,用于后续的跟踪(包括防止这个变异被发布到线上,以及在攻防演练活动中进行计分)。
  注入的原则有:
  在被提交的commit里的文件才注入。
  变异尽量只注入被提交的commit中增加和修改的行。
  变异也可以注入被提交的commit中增加和修改的行的附近,例如,交换if/else,或者去除try/catch。
  确保变异注入后的代码仍然是可以编译通过的。
  注入的变异可以是方法(Method)级别的,也可以是类(Class)级别的。
  我们比较了多个注入方式,最终采用以上注入方式。这是因为其他注入方式或多或少有一些我们无法接受的问题,例如:
  通过直接提交commit的方式来注入Bug。这样做,注入很容易就会通过代码评审和比对git版本历史被注意到,而这两种方式是很常用的问题排查手段,在攻防中不应禁止。
  单独拉一个代码分支来做攻防。这样虽然能确保被注入的代码不会被误发到线上,但同样很容易就在代码评审和比对git版本历史中被注意到,从而大大降低攻防演练的价值。
  直接在线下环境进行运行时的代码注入。虽然直接做运行时的代码注入的技术是成熟的,例如jvm-sandbox,但是线下环境以及在线下环境上运行的测试只是线下质量的一部分。如果只在线下环境做内存注入,就无法检验代码评审、单元测试和接口测试、代码扫描等质量保障手段的水平。另外,在线下排查问题时,工程师通常会进行代码走读,所以应该确保运行的代码和git里的代码是一样的。
  (3)发现和计分。一次攻防演练活动可以持续几周(因为很多项目和迭代的时间跨度是几周)。对于演练中的每个变异,评分规则是:
  在代码进入remote的项目分支或迭代分支前发现并修复的,得10分。
  在代码进入master前发现并修复的,得6分。
  在项目提交发布前修复的,得3分。
  意外修复,不得分。
  意外修复的情况包括:变异的代码随着其他代码一起被删除、重构。对于意外修复,如果红军给出证据(例如代码评审、CI错误日志等),证明变异其实已经被发现了,可以算作主动修复。
  (4)确保变异不被发布到线上。线下质量红蓝攻防的一个关键点是确保注入的变异不会被发布到线上(否则可能引起故障)。对此,我们采取的方案是利用poisoncommit的机制。poisoncommit(有毒的commit)的大致原理如下:
  变异注入成功、请求合并成功后,我们会把被注入的commit3db178cc标记为一个poisoncommit。只要3db178cc没有antidote(解药),任何含有3db178cc的代码版本都不会被发布上线。
  如果3db178cc里的变异被修复了,那么该commit会被记作3db178cc的antidote。有了antidote,代码发布就不会被阻拦了。
  poisoncommit本身是一种常用的发布阻塞机制,例如,确保在hotfix分支的代码没有合并回master之前,master的代码不会被误发布上线。在攻防演练的场景中,注入的变异被记在一个私有的poisoncommit列表里,用来防止作弊。

  2.报文注入
  微服务架构里的服务之间是通过API和消息进行交互的。我们把API的request(请求)、response(返回)及消息体统称为报文。过去的测试自动化对报文内容的校验做得不够,导致一些问题到项目晚期进行更大范围的集成和联调时才被发现,甚至有些问题被遗漏到了线上。
  测试用例的操作过程如图1-7所示。在一个特定的用例中,我们希望当被测系统调用它的下游时,如果传递了错误的金额(RequestY的里面的cent字段的值不是100),用例就报错。有时候这样的问题可以被E2E(端到端)的测试发现,有时候这样的问题在E2E测试中也会被遗漏。
▲图1-7测试用例的操作过程

  因此,我们想要回答的问题是:我们的自动化测试用例是否对报文做了充分的校验。我们希望通过技术手段,以一种全自动化的方式来客观量化地回答这个问题。
  我们选择的技术方案是:用jvm-sandbox在用例的运行时对报文进行注入,改变某个字段的值,或者增加、减少字段。和上文的基于代码变异的手段类似,我们对报文注入进行工程化的注入和测试,得到测试用例集对报文注入的发现率。这个发现率也是一种测试有效性的度量指标。
  单服务级别测试(单元测试、接口测试)的部分实际度量结果如表1-3所示。

▼表1-3单服务级别测试的部分实际度量结果

  在单服务级别,理论上我们希望对报文内容校验的有效性是100%,即报文中的所有问题都会被发现。但实际工作表明:在单系统层面,无法判断某些字段的值正确与否。这些报文字段必须和上下游其他系统的状态结合起来才能判断。从经验数据来看,单服务级别测试的报文内容校验的有效性如果能达到80%~90%,那么大部分的问题就能在E2E之前被发现了。

查看《阿里测试之道》全部连载章节
版权声明:51Testing软件测试网获得作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任
21天更文挑战,赢取价值500元大礼,还有机会成为签约作者!

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

法律顾问:上海漕溪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2022, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号