目标:
- 输入:变更的代码
- 用例预分析:
- 变更代码 -> 知识库查找变更对应代码 -> 函数对应用例
- 新增函数 -> 提醒去分析和补充用例
- 输出:推荐测试的用例
价值: 提高测试的分析效率和质量。
建立用例和代码关系:动态获取函数调用链
确认用例匹配的粒度:函数
通过插桩获取函数的调用关系。
插桩:在保证被测程序原有逻辑完整性的基础上,在程序中插入批量的探针,通过探针的执行并抛出程序运行的特征数据,通过对这些数据的分析,可以获得程序的控制流和数据流信息。
- 源代码插桩:通过编译的方式将探针插入到源代码中。(GCT)
- 中间代码插桩:如Java编译生成.class字节码文件,将探针插入.class文件中。(Jacoco,Emma)
- 二进制代码插桩:对程序真正运行的目标文件插桩。(XDebug)
方案设计
变更分析
- SVN diff :代码文件变更,对于一些无效变更(如未调用代码变更、空行、函数变换位置),当前方式会认为其发生变更。
- 二进制对比:编译器优化原因可能导致同一段源代码编译出不同的二进制。
结合 SVN diff 和二进制变更,精准获得变更的函数。
变更函数 -> 变更用例
获取变更函数后,根据变更函数找到其对应的用例 ID,再根据用例 ID 查询用例详情。
变更接口和边界耦合关系
公共接口变更时需要识别并通知对应测试。
优化
减少函数对应的用例集
存在问题:
- 用例和函数的分支内容息息相关,回归测试时需要覆盖当前分支,但并不需要覆盖该分支的重复用例。
- 不重复的用例中,如果函数改动后,用例和分支的关系已经无效,同样为无效用例。
解决方案: 对函数只关联一个最精简的测试用例集。覆盖函数的每一个分支。
- 对函数路径分支进行标记:在跳转指令处进行插桩
- 提取路径分支hash:
- 遍历函数,递归函数基本块
- 遍历基本块指令,提取块首位地址
- 解析指令,是条件跳转则提取路径分支个数,计算路径分支hash。建立每个基本块地址与路径分支hash映射关系
- 用例与函数路径分支的关联关系的建立:用例采集过程中,将命中的插桩地址取出来,与第二部建立的映射关系进行匹配,找到命中插桩地址对应的路径分支hash
差异性分析到分支级别
在用例关联上做到了分支级别的关联,但在差异化分析中还只是函数级别,两者不对称造成了用例冗余。
匹配变更和函数分支hash
基本思想: 只要路径分支的条件判断一样,说明它们在函数的执行过程中的路径是相同的,基本块跳转顺序也是一样。这样通过相同分支条件判断就可以匹配前后发生变更的函数路径分支。
实现步骤:
- 计算变更函数的基本块对应的路径分支、路径分支的判断条件的hash值
- 建立变更函数的基本块、函数路径分支hash、路径分支条件判断hash三者建立映射关系
- 在数据库中查找与路径分支条件判断hash相同的路径分支hash
用例分支和变更分支关联
- 数据库建立起用例与路径分支hash、路径分支条件判断hash的关联关系
- 差异化分析后通过变更函数路径分支条件判断hash找到对应的路径分支hash
- 将差异化分析中的路径分支hash和数据库中的路径分支hash对比,查找不相同的路径分支hash。该条用例即需要回归的用例。