测试覆盖率 精准测试是怎么把测试用例和代码关联起来的呢?

Ikaros灬 · 2021年08月04日 · 最后由 陈恒捷 回复于 2023年09月11日 · 9284 次阅读

最近在研究精准测试,看了许多文章,都只是讲的大概,最关键的一步,测试用例是怎么和代码关联起来的呢?求大佬们解答

共收到 42 条回复 时间 点赞

非常深奥的问题……双向绑定,依然是个难点。

之前尝试过将用例与接口关联起来,通过接口代码调用关系把代码串联起来,实现用例与代码关联;还尝试过,执行单个用例,然后统计覆盖率,将覆盖的代码与用例关联起来,但是都比较复杂,比较难用,而且保持更新是个难点,成本比较高

从目前我看到的几类方式上看:

基本原理上,大多是通过覆盖率来关联的。比如执行 A 用例的时候,通过覆盖率数据可以知道会执行到 a 函数。然后记录下 A 用例->a 函数 这个关系。后面如果 a 函数有变更,就会认为 A 用例需要执行。这里面也会有一些精细化的调整,比如可能会细化到函数内部的 if else 分支级别,或者结合一些算法来减少推断出来的用例数(比如一个底层网络库调用调整,全部涉及接口交互的用例都自动出来了,但实际可能只需要执行任意一条即可校验)

也有的是到接口级别,执行 A 用例,会调用 a 接口,那映射关系就是 A 用例->a 接口。 只要 a 接口有变更,A 用例就要执行。接口级别甚至可以不用覆盖率,只需要日志打印。

还有只是反推到接口级别的,通过 ASM 分析(通俗点说,有点类似于平时 idea 里的 find usage 倒推调用位置,一直倒推到 controller 层)+ 运行时数据采集(比如通过反射来调用的,就只能用这种了),反推某次代码改动影响到哪些接口,然后执行这些接口相关的接口测试用例。客户端类型的话把接口改为界面(activity/fragment/view/url),也可以同理推断

不过怎么维护好 测试用例->代码(函数/行/接口)这个映射关系,除了接口测试用例天然自带映射关系外,目前还没见到有特别好的招。

测试用例和代码关联这个思路本质上就是错的,永远走不到自动化的路上,需要人维护的东西终不会可靠

其实对于 springboot/springcloud 的应用来说精准测试的思路相对简单,其他技术栈就不是很清楚了:

  • 如楼上恒捷所说,根据变更扫出调用链,找到最上层的@Component@PostConstruct@Controller/@RestController 这些组件里面对应的接口;
  • 服务端无条件上 swagger,不配合就不要玩下去,要么自己实现一个类似的框架。根据用接口参数定义,扫出 required 的参数,用 testdata-service 构造出对应的数据,对于非 required 的参数,可以使用 pairwise/正交算法去组合,同样拿 testdata-service 构造出对应的数据,最后把数据拼装好;
  • 在测试运行时,临时创建接口测试用例,这只是对框架要求稍微高一点而已,拿上数据去跑就行了;
  • 总而言之,要精准测试,一定要放弃写脚本、写 case 去 mapping code 的错误思路,用框架在运行时临时创建可执行的内容,不理解的话请参考 swagger-ui 里面的 try-out 功能。

正因为我一直坚持这个观点,所以我在任何公司都不会搞用 web 页面管理自动化测试用例的这种测试平台,这种玩意对未来不友好,看起来傻极了——未来应该是 mr 提交,变更代码涉及到的接口/功能自动创建测试并且执行——当然,我说的这个方法,数据库层有业务逻辑代码(oracle、pg 的 package,各种数据库的 procedure、function)的不适用,变更的是配置而不是代码的不适用,因为测试通过并不能说明没有 bug~
补充一下:如果谁有种,把 bug 自动修复做了才算牛逼,据说 github 上有个搞这事的项目!

槽神 回复

我思考过这个,但是这样测试的话,和全量跑自动化貌似没什么区别哇,一个是跑了改动部分的自动化,一个是跑了全量的自动化。。。跑 5 分钟和跑 1 小时的区别。。

Ikaros灬 回复

那你精准测试要解决什么问题?

恒温 回复

我看到的思路是,在用例执行的时候,点一下开始执行,清除掉服务器上的覆盖率,然后执行完了点结束执行,再把覆盖率 dump 下来,分析执行到的代码,获取到调用链,做关联,但是不确定这样子是否可靠

陈恒捷 回复

对,我看到的也是这样的,但是不知道这种方案到底是否精准。。也不知道目前业界做的比较好的精准测试时什么样子的。

槽神 回复

我觉得主要是解决手工回归范围大的问题吧,缩小测试范围,跑自动化用例效果可能不那么明显。。

Ikaros灬 回复

精准测试天生就不是手动的,手动用例还是通过沟通和基于风险策略去选择回归范围吧

槽神 回复

非常同意临时创建测试案例的策略,这样节省太多维护成本了

32楼 已删除
槽神 回复

我还有个疑问,自动生成的用例,测试结果怎么校验呢?

Ikaros灬 回复

结果校验的核心是 output data,自然交给 testdata-service 一起构造,这样需要维护的是每个功能的造数规则,这种规则只会随着业务功能的逻辑变化而变化,不会触及代码层面,而且可以通过录制(预先跑几遍)来构造,很简单。

补充说一下,既然问到了输出校验,接下来你肯定还会问,如果我这个接口/功能/步骤的测试根本不足以校验出这个改动是否影响到后续业务的正常开展,比如银行开户功能改了并且测试通过也不能保证这个改动不会导致后续取不出钱来,这种情况怎么办。这个就比较麻烦了,继续吹几句,仅供参考:

  • 流程性、依赖性的自动测试需要 MBT 来配合实施,也就是业务流程建模,你可以简单的理解为把每个功能点作为一个节点,流程用有向图连起来,构造、画图用 proxy 挂 mock-server 录制就可以实现基本的画图了,后续根据实际业务稍加修改就行,然后每个节点做一下业务功能标注和描述,推荐使用 canvas/svg,之前一个小伙伴用 graghviz,卡在图的编辑上很久,而且也比较重了;
  • 变更代码涉及到其中的某一个或者几个节点的时候,你可以遍历这张图找到所在的位置,DFS 也好、BFS 也罢,达到目标就行了,我记得去年字节有篇公众号文章写过他们做 app 端便利测试的时候提过类似的方法,反正就是基础图论应用;
  • 根据涉及到的节点在这个有向图中的位置,向上溯源和向下延展,给出所有路径,让框架和 testdata-service 根据这几条通路帮你组织好前后依赖的所有数据,包含输入和输出;
  • 测试框架生成这个全流程所有的 case,然后串联起来执行,多个流程在一个节点上是共用一份 case 还是每条路径重新生成就看你的机器资源和对效率的要求了。

基于代码变更的模型化测试,我管它叫 CMBT,以前几个伙伴搞过,无疾而终,并非实力不济,而是领导听不懂~

槽神 回复

这个要做出来得靠团队了。。。

槽神 回复

这要能做出来,测试都可以改行了

槽神 回复

自动修复 bug = 自动开发软件,开发也省了😄

2 年前做过,当时想的是给自动化回归测试当补充。后面弃用了。一个是用例规模不大,没这必要,全跑也多不了多少时间;另外就是用例质量不高,自动化测试覆盖都没到位,搞这个不合时宜。再后来公司搞开发优先,测试有点技术的要么干开发,要么跑路,已经没做下去的必要了。

大概方法是,在已经建设好自动化测试跑一遍,通过 javaagnt 把用例和用例覆盖的代码(到方法级)保存到数据库,然后提交代码的时候去拉取要跑的用例,达到精准测试的目的。

嗯代码还在内部 git 上

Thirty-Thirty 回复

facebook 还真做过这个自动修复 bug 的系统:https://www.jiqizhixin.com/articles/Facebook-ai-dubug-tool-SapFix

Ikaros灬 回复

建议你可以买本《不测的秘密:精准测试之路》看看。不知道算不算是业内做得最好的(毕竟大部分实际效果你没在公司内实际用,都不好说),但应该算目前公开资料里最全的了。

陈恒捷 回复

还有只是反推到接口级别的,通过 ASM 分析(通俗点说,有点类似于平时 idea 里的 find usage 倒推调用位置,一直倒推到 controller 层)+ 运行时数据采集(比如通过反射来调用的,就只能用这种了),反推某次代码改动影响到哪些接口,然后执行这些接口相关的接口测试用例。客户端类型的话把接口改为界面(activity/fragment/view/url),也可以同理推断

非常赞同上面这个思路,我们现在的精准测试就正准备尝试这种方法。

之前去 QEcon 大会,有个工商银行的分享。提出了两个思路,一个是按照时间段,另外一个是用例打标(这个不懂怎么实现),感觉可操作性性都不强。

流程性、依赖性的自动测试需要 MBT 来配合实施,也就是业务流程建模,你可以简单的理解为把每个功能点作为一个节点,流程用有向图连起来,构造、画图用 proxy 挂 mock-server 录制就可以实现基本的画图了,后续根据实际业务稍加修改就行,然后每个节点做一下业务功能标注和描述,推荐使用 canvas/svg,之前一个小伙伴用 graghviz,卡在图的编辑上很久,而且也比较重了;

这个把业务点用有向图串联起来,现在运维的基础设施上了 skywalking 以后,就感觉很好做了,直接把数据迁移或者爬取下来就可以,而且调用链路非常清晰。

陈恒捷 回复

该工具可以为特定 Bug自动生成修复程序,然后将其提交给工程师批准并部署到生产中。

看来一时半会儿人工智能还是取代不了工人智力

Thirty-Thirty 回复

里面也有说,之所以保留工程师批准,只是因为如果出问题线上可能有较大影响,所以还是保留了人工二次确认。实际上准确度能提高到一定程度,加上自动的灰度校验,这道关卡就可以去掉了。

这个算是一个正向循环,bug 案例越多->自动化处理比例越高,准确度越高->人工介入程度越低。

不过这个 18 年提出的,后续也没见到有什么更新,不知道是不是已经夭折了。

这东西无法落地的,目的是什么。。

精准测试的目的,应该是在减少测试内容的同时,也能有效保障改动引起的质量风险。

虽然目前各种原因还没有类似接口测试这么成熟的落地方案,但梦想总归要有的,不成熟不也等于有机会么。

这个思路很难成立,有个前提就很难保证,需要相信开发的代码,不然只能全量覆盖

homin 回复

看来背后有故事

homin 回复

说出你的故事

陈恒捷 回复

当初做服务端测试时,拿着开发给的设计文档写测试用例,被 P9 级大佬叼到无地自容,重写了 5 6 次用例😢

homin 回复

额,基于设计文档来调整用例我也挺常做的,P9 大佬是说有啥问题?

陈恒捷 回复

不建议用这个思路去设计用例。
跟着开发的代码思路、设计思路写用例,和开发写的单元测试场景重复性高,会被开发带偏,容易忽略特殊的业务场景(可能开发漏了该业务场景的考虑),假设开发写了额外的代码逻辑在设计文档中未体现,就无法保证代码覆盖率等。

Ikaros灬 回复

覆盖率拿到的调用链仅仅是单应用服务内部的,可以看看 skywalking

homin 回复

哦哦,我明白你意思了。
我是基于需求先写用例,然后根据设计文档进行补充调整(有一些实现细节通过,设计文档会更清晰,也更容易拆分和针对性测试)。你是直接基于设计文档写用例,确实容易走偏。

陈恒捷 回复

因为我们那的需求都是单服务的需求,每个单服务都能够独立执行,所以没有一些外部需求背景,只有一份设计文档

homin 回复

好奇问下,那你们后面是怎么解决这个问题的?怎么去设计测试用例避免被带偏或者遗漏?

之前做过建立关联关系的工具,但是比较粗略。大概思路如下,通过 selenium 起一个 web,这个 web 只监听预设好的待测服务和用例管理平台。当用例管理平台操作某个用例通过/不通过的时候,记录这个用例信息 + 这段时间所有的 API。通过 API 就能得知 后端哪些接口跟这个用例相关。

槽神 回复

这种思路我比较赞成,并且想这样去实现落地,但是用例执行怎么保证有效,前期数据构造是个难点,还有 testdata-service 这个不太清楚怎么实现的,大佬有空指点下

陈恒捷 回复

这个《不测的秘密 - 精准测试之路》有电子版可以共享一下么

陈恒捷 回复

两年过去了,怎么维护好 测试用例->代码(函数/行/接口)这个映射关系,不知道对于这种思路现在有没有更好的办法

清水 回复

这个《不测的秘密 - 精准测试之路》有电子版可以共享一下么

我当时是购买纸质书的,不清楚有没有电子版。你可以试试找下。书本身也不算贵,加上很多时候买书有折扣,推荐可以买一本看看。

两年过去了,怎么维护好 测试用例->代码(函数/行/接口)这个映射关系,不知道对于这种思路现在有没有更好的办法

暂时没见到更好的办法,更多见到的是放弃关联用例,转而只是反推影响的界面或者接口,相对更简单靠谱。

陈恒捷 回复

好的,谢谢,我也入手了这个书。那对于反推影响的界面或者接口这种方式,有推荐的文章或者案例分析吗?

清水 回复

可以看看最近 3 年左右 MTSC 大会上,精准测试相关的议题。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册