1. 变异测试的基本流程,变异算子(Statement Deletion、Operator Replacement、Condition Negation 等)如何生成变异体(Mutant)?请为每种算子举例说明。
请阐述变异测试的基本执行流程,说明变异算子(如语句删除、运算符替换、条件取反等)是如何生成变异体(Mutant)的,并为每种算子给出具体示例?
- 变异测试的完整流程(生成变异体→运行测试→统计存活/被杀→计算变异得分)
- 各类变异算子的定义与作用
- 变异体与原始程序的对应关系
变异测试的基本流程包括:首先,变异工具对原始程序源码应用变异算子,自动生成一批语法上合法但语义上略有缺陷的"变异体";然后,对每个变异体运行原始测试集;如果一个变异体至少被一个测试用例"杀死"(即测试失败,检测到行为差异),则该变异体被标记为 Killed;若所有测试都通过,则该变异体 Survived(存活),说明现有测试没有覆盖到该变异所涉及的代码逻辑;最后,用被杀死变异体数除以总变异体数(剔除等价变异体后)得到变异得分。常见的变异算子包括:Statement Deletion(语句删除,如删掉一个 sum += a 语句,使结果丢失累加)、Operator Replacement(运算符替换,如把 + 改成 -)、Condition Negation(条件取反,如把 if (age >= 18) 改成 if (age < 18))、常数替换(把 1 改成 0)、返回值替换(把 return true 改成 return false)等。每种算子都会在某一处代码注入一个微小但可观察的缺陷,从而检验测试用例能否捕获该缺陷。
变异测试的核心理念是"测试也需要被测试"——好的测试用例应当能捕获任何微小的行为偏差。通过系统地注入缺陷,可以量化测试套件发现缺陷的能力。变异得分越高,说明测试对程序行为的约束越强。
// 原始代码:根据年龄判断是否成年
public boolean isAdult(int age) {
boolean result = age >= 18;
return result;
}
// 变异体1(条件取反):age >= 18 -> age < 18
public boolean isAdult(int age) {
boolean result = age < 18; // 变异算子:Condition Negation
return result;
}
// 变异体2(返回值替换):return result -> return false
public boolean isAdult(int age) {
boolean result = age >= 18;
return false; // 变异算子:Return Replacement
}