第1页
Test Oracle(测试预言)
第2页
自动驾驶汽车——如何测试?
测试问题: 相同输入,结果可能不同,很难构造测试预言。
- 汽车因雨中行驶以及太阳方位问题,无法识别路标甚至行人;
- 摄像头在灰暗天空下无法识别白色汽车;
- 当公交车汇入车流时,系统误判其会停车。
→ 致命碰撞事故
深度神经网络被用于自动驾驶。
第3页
两个基本问题(Two Fundamental Problems)
充分性准则(Adequacy Criteria)
测试预言(Test Oracle)
├── 无测试预言(No test oracle)
└── 无自动化测试预言(No automated test oracle)第4页
无测试预言(No Test Oracle)
某些类型的应用程序特别难以测试,因为不存在"测试预言":
- 机器学习、离散事件仿真、优化、科学计算……等
即使没有预言,也可以通过检测软件是否违反某些属性来发现缺陷。
第5页
机器学习与大数据(Machine Learning & Big Data)
(本页为示意图/场景图)
第6页
仿真与医疗健康(Simulation & Health Care)
(本页为示意图/场景图)
第7页
示例1:Sin(x) 函数
| 测试用例 | 输入 | 预期输出 |
|---|---|---|
| 测试用例1 | 30° | 0.5 |
| 测试用例2 | 29.999° | ?(难以确定) |
第8页
示例2:两节点间最短距离
(图中节点编号1~7)
| 测试用例 | 输入 | 预期输出 |
|---|---|---|
| 测试用例1 | 上图,节点1 → 节点4 | 2 |
| 测试用例2 | 上图,图中圈出的两节点 | ?(难以确定) |
第9页
蜕变测试(Metamorphic Testing)
核心思想:
- 若新测试用例输出
f(t(x))符合预期,不一定代表结果正确; - 但若
f(t(x))不符合预期,则f(x)或f(t(x))中至少有一个是错误的。
原始测试用例: x →[f]→ f(x)
↑ 伪预言
转换函数 t
↓ 伪预言
新测试用例: t(x) →[f]→ f(t(x))转换函数基于函数 f 的蜕变属性构造。
参考文献:T.Y. Chen, S.C. Cheung, S.M. Yiu,《蜕变测试:一种生成后续测试用例的新方法》,技术报告 HKUST-CS98-01,香港,1998。
第10页
示例1——蜕变测试:Sin(x) 函数
蜕变关系(MR): Sin(x) = Sin(x + 2π)
| 项目 | 内容 |
|---|---|
| 测试用例 | — |
| 原始输入 | 29.999° |
| 新输入 | 29.999° + 2π |
| 验证MR是否成立 | Sin(29.999°) = Sin(29.999° + 2π)? (待验证) |
第11页
示例2——蜕变测试:两节点间最短距离
设函数 ShortestDis(x, y),其中 x 为起始节点,y 为终止节点。
蜕变关系(MR): ShortestDis(x, y) = ShortestDis(y, x)
| 项目 | 内容 |
|---|---|
| 原始输入 | x1 为起始节点,y1 为终止节点 |
| 新输入 | y1 为起始节点,x1 为终止节点 |
| 验证MR是否成立 | ShortestDis(x1, y1) = ShortestDis(y1, x1)?(待验证) |
第12页
随堂测验(Quiz)
请使用蜕变测试,为以下两个示例定义新的蜕变关系(MR):
- 示例1: Sin(x) 函数
- 示例2: 两节点间最短距离函数
ShortestDis(x, y),其中 x 为起始节点,y 为终止节点。
第13页
示例3:统计计算程序 CSta
public static void CSta (int[] numbers) {
int length = numbers.length;
double var, mean, sum, varsum;
sum = 0.0;
for (int i = 0; i < length; i++) {
sum += numbers[i];
}
mean = sum / (double) length;
varsum = 0.0;
for (int i = 0; i < length; i++) {
varsum = varsum + ((numbers[i] - mean) * (numbers[i] - mean));
}
var = varsum / (length - 1.0);
System.out.println("length: " + length);
System.out.println("mean: " + mean);
System.out.println("variance: " + var);
}该程序计算整数数组的长度、均值和方差。
第14页
随堂测验(Quiz)
(与第13页相同的 CSta 代码)
问题:请为该程序设计蜕变关系(MR)?
第15页
蜕变关系(Metamorphic Relation)示例
MR 1:对称输入,均值为零
| 项目 | 内容 |
|---|---|
| 测试输入 | [a, -a, b, -b] |
| 结论 | mean = 0 |
MR 2:所有元素加1,均值也加1
| 项目 | 内容 |
|---|---|
| 测试输入1 | [a, b, c, d] → 均值为 mean1 |
| 测试输入2 | [a+1, b+1, c+1, d+1] → 均值为 mean2 |
| 结论 | mean2 = mean1 + 1 |
第16页
无自动化测试预言(No Automated Test Oracle)
某些类型的应用程序特别难以测试,因为不存在自动化的"测试预言":
- 多媒体应用、人机交互……等
第17页
测试输入 → 测试输出
预期输出:更美观!(more beautiful!)
(本页展示图像处理场景,输入一张图片,期望输出经过处理后更美观的图片,但"更美观"难以自动判断)
第18页
一种解决方案(One Solution)
当不存在自动化预言时,应降低人工检查测试结果的成本。
第19页
自动化测试流程
自动化测试数据生成
↓
自动化测试执行
↓
自动化测试输出收集
↓
(人工判断)更美观?(说明:前三个步骤可自动化,最终的"是否更美观"仍需人工判断,目标是最小化人工介入的成本)
第20页
课后作业:蜕变测试——自动驾驶汽车
两种图像变换方式:
| 变换类型 | 说明 |
|---|---|
| 线性变换 | 调整图像的亮度和对比度 |
| 卷积变换 | 对图像进行模糊处理,或添加雨/雾效果 |
蜕变关系设计(角度变化可适当松弛):
MSE_orig:原始图像与原始输出之间的均方误差;λ:可调节的参数;- 左侧:经变换后的输出与原始输出之差的平方。
作业要求: 应用蜕变测试对自动驾驶汽车进行测试。
第21页
测试用例集约简(Test Suite Reduction)
(本页为章节标题页)
第22页
测试用例集约简——最小子集
覆盖矩阵(行为需求 r1r6,列为测试用例 t1t5):
| 测试用例 | r1 | r2 | r3 | r4 | r5 | r6 |
|---|---|---|---|---|---|---|
| t1 | 1 | 1 | 1 | 1 | 0 | 0 |
| t2 | 0 | 0 | 1 | 1 | 1 | 0 |
| t3 | 0 | 0 | 1 | 1 | 0 | 1 |
| t4 | 0 | 0 | 0 | 0 | 1 | 1 |
| t5 | 1 | 1 | 0 | 0 | 1 | 0 |
所有最小子集(覆盖全部需求的最小测试用例组合):
{t1, t2, t3}{t1, t4}{t1, t3, t5}{t2, t4, t5}
第23页
贪心算法用于测试用例集约简(Greedy)
覆盖矩阵同上。
贪心算法执行过程: 每次选择覆盖最多未覆盖需求的测试用例。
| 步骤 | 选择 | 说明 |
|---|---|---|
| 第1步 | t1 | 覆盖 r1, r2, r3, r4(共4个) |
| 第2步 | t2 或 t4 | 继续覆盖剩余需求 |
| 第3步 | … | … |
贪心算法结果: {t1, t4}
第24页
附加贪心算法(Additional Greedy)
覆盖矩阵同上。
附加贪心算法执行过程: 每次选择覆盖最多新增未覆盖需求的测试用例(避免重复覆盖)。
| 步骤 | 选择 | 新增覆盖需求 |
|---|---|---|
| 第1步 | t1 | r1, r2, r3, r4 |
| 第2步 | t4 | r5, r6 |
附加贪心算法结果: {t1, t4}
第25页
随堂测验:附加贪心算法(Quiz: Additional Greedy)
覆盖矩阵同上。
问题: 若第1步选择失败(Fail),请用附加贪心算法重新执行,给出最终结果。
(提示:尝试从不同的初始测试用例出发,观察结果是否仍为最优子集)
第26页
复杂度分析(Complexity)
测试用例集约简问题 ≈ 最小基数命中集问题(Minimum Cardinality Hitting Set)
两者在计算复杂度上等价,属于 NP 难问题,因此贪心算法是常用的近似求解方法。
第27页
讨论(Discussion)
冗余真的无用吗?(Is redundancy useless?)
(引导思考:测试用例中的冗余是否在某些情况下仍有价值,例如提升故障检测的鲁棒性)
第28页
故障邻近性(Failure Proximity)
流程图:
测试数据 → 转换(Transform)→ 映射函数(Mapping Function)→ 机器学习(Machine Learning)
↓
聚类采样(Cluster Sampling)
↓
故障(Faults)思路:通过将测试数据映射到特征空间,利用聚类分析使相似行为的测试用例聚集,从每个簇中采样,从而减少冗余同时保留故障检测能力。
第29页
软件行为学习(Software Behavior Learning)
整体流程:
软件(Software)
↓
行为特征提取(Behavior Features)
↓
距离计算(Distances)
↓
聚类(Clustering)
↓
采样(Sampling)
↓
测试数据(Test Data)→ 分析(Analysis)第30页
距离计算(Distance)
覆盖矩阵同前:
| 测试用例 | r1 | r2 | r3 | r4 | r5 | r6 |
|---|---|---|---|---|---|---|
| t1 | 1 | 1 | 1 | 1 | 0 | 0 |
| t2 | 0 | 0 | 1 | 1 | 1 | 0 |
| t3 | 0 | 0 | 1 | 1 | 0 | 1 |
| t4 | 0 | 0 | 0 | 0 | 1 | 1 |
| t5 | 1 | 1 | 0 | 0 | 1 | 0 |
示例: t1 与 t2 之间的汉明距离(Hamming Distance)= 4
(两个向量中对应位置不同的元素个数,即 r1、r2、r5、r6 四个位置不同)
