选择测试数据本身就是一项技能。普通数据说明算法能运行;空数据、单项数据和重复数据则检验它在边缘情况下是否仍然正确,而大多数错误就藏在边缘。
本课为搜索、排序与文件收尾。它用到验证、核实与测试里的测试用语,以及追踪线性搜索里的追踪表。
应该试哪些棘手的情况?
- 空: 完全没有项目。
- 单项: 最小的非空列表。
- 全部相等: 每个值都一样。
- 答案有重复: 最大值或目标出现不止一次。
- 答案在两端: 第一个或最后一个位置。
例题
任务:在有 Count 个项目的数组 Scores 中找出最高分,并说出它出现了几次。第一个版本,带有空数据保护:
IF Count = 0 THEN
OUTPUT "No data"
ELSE
Max ← Scores[1]
Times ← 1
I ← 2
WHILE I <= Count
IF Scores[I] > Max THEN
Max ← Scores[I]
Times ← 1
ELSE
IF Scores[I] = Max THEN
Times ← Times + 1
ENDIF
ENDIF
I ← I + 1
ENDWHILE
OUTPUT Max, Times
ENDIF
测试:Scores = [8, 5, 8, 3, 8],Count = 5。
| I | Scores[I] | Max | Times |
|---|---|---|---|
| 开始 | 8 | 1 | |
| 2 | 5 | 8 | 1 |
| 3 | 8 | 8 | 2 |
| 4 | 3 | 8 | 2 |
| 5 | 8 | 8 | 3 |
输出:8, 3。最高分是 8,出现了三次。
测试:空,Count = 0。 保护语句会拦住它并输出 No data。没有这个保护,Scores[1] 就会指向一个不存在的项目。
测试:单项,Scores = [9],Count = 1。 Max = 9,Times = 1。循环从 I = 2 开始,它大于 Count,所以循环体一次也不执行。输出:9, 1。
要留意的错误
一位学生为了“把相等的值也包括进来”,把比较改成 >=:
IF Scores[I] >= Max THEN
Max ← Scores[I]
Times ← 1
在 [8, 5, 8, 3, 8] 上,I = 3 时 8 满足 >=,所以 Times 被重置为 1,而不是增加到 2。I = 5 时又重置一次。最终输出是 8, 1,这是错的。
改正方法是:新的最大值仍用 >,再用单独的 = 分支来数重复。这个错误版本只有在重复数据下才会暴露,这就是重复数据测试重要的原因。
自我检测
使用例题里的算法。
1. Scores = [4, 4],Count = 2。输出是什么?
Show answer
开始时 Max = 4,Times = 1。I = 2 时,4 等于 Max,所以 Times 变为 2。输出 4, 2。
2. Scores = [2, 7, 7, 7],Count = 4。输出是什么?
Show answer
开始时 Max = 2。I = 2 时,7 > 2,所以 Max = 7,Times = 1。I = 3 时,Times = 2。I = 4 时,Times = 3。输出 7, 3。
3. 说出三个用来检查“找出列表中最小值”算法的测试用例。
Show answer
例如:一个空列表、一个单项列表,以及最小值出现两次的列表。最小值在最后一个位置的列表也值得一试。
接下来学什么
把整个模块用到综合练习中,并把每一次失误记入错题记录与重测队列。
如果你习惯只测试题目附带的那个例子,我们的老师可以通过一对一线上计算机科学补习帮你养成测试边缘情况的习惯。