捕获常见错误
传统的测试观点是将其视为检查代码是否按预期工作的过程。单元测试在这方面表现出色,并自动化了使用已知输入运行代码并检查预期输出的过程。由于我们是人类,我们在编写代码时都会不时犯错误,其中一些错误可能会产生重大影响。我们可能会犯一些常见的简单错误,而单元测试擅长捕捉所有这些错误。最常见的错误包括:
-
差一错误(Off-by-one errors)
-
条件逻辑颠倒(Inverted conditional logic)
-
缺少条件(Missing conditions)
-
未初始化的数据(Uninitialized data)
-
错误的算法(The wrong algorithm)
-
损坏的相等性检查(Broken equality checks)
例如,回到我们之前的小写用户名测试,假设我们决定不使用内置的 String.toLowerCase()
方法来实现,而是尝试编写自己的循环代码,如下所示:
public class Username {
private final String name;
public Username(String username) {
name = username;
}
public String asLowerCase() {
var result = new StringBuilder();
for (int i = 1; i < name.length(); i++) {
char current = name.charAt(i);
if (current > 'A' && current < 'Z') {
result.append(current + 'a' - 'A');
} else {
result.append(current);
}
}
return result.toString();
}
}
我们会立即发现这段代码不正确。测试失败,如下图所示:

Figure 1. Figure 5.3 – A common coding error
这段代码中的第一个错误是一个简单的差一错误——输出的第一个字母缺失了。这表明我们在初始化循环索引时出现了错误,但这段代码中还有其他错误。这个测试揭示了两个缺陷。进一步的测试还会揭示另外两个缺陷。你能仅通过视觉检查看出它们是什么吗?与使用自动化测试相比,像这样在头脑中分析代码需要多少时间和精力?