0%

怎样才能称之为“好”的测试用例

单元测试是验证代码正确性的重要工具。但 写出好的测试用例却远远不只是关于验证正确性 – 为了保证可读与可维护,一个测试用例还需要拥有其他几项属性。

其中之一,就是 Clarity

Clarity意味着一个测试用例对于人来说应该是一个可读的文档,用以通过public API描述待测代码的能力。
测试用例不应该依赖于实现细节。一个类的测试用例的名字应该能讲清楚这个类在做什么,并且测试用例也应该作为使用该类的样例。

另外两个重要的属性是完整性(completeness)以及简洁性(conciseness)。 译者注:相比简洁性,高信噪比可能是更合适的描述方式。
只有当测试用例的Body包含了所有用以理解TA的信息时,才能称之为完整的;只有当测试用例不包含任何的多余信息时,才能成指为简洁的。
下面的测试用例在这两个方面都跪下了:

1
2
3
4
5
6
@Test public void shouldPerformAddition() {
Calculator calculator = new Calculator(new RoundingStrategy(),
"unused", ENABLE_COSIN_FEATURE, 0.01, calculusEngine, false);
int result = calculator.doComputation(makeTestComputation());
assertEquals(5, result); // Where did this number come from?
}

非常多多余且令人分心的信息被传入了构造函数,且重要的信息被隐藏在了一个helper方法中。测试用例可以通过明确helper方法的目的来增强完整性,可以通过另一个helper方法隐藏构造calculator时不相关的细节来提高简洁性:

1
2
3
4
5
@Test public void shouldPerformAddition() {
Calculator calculator = newCalculator();
int result = calculator.doComputation(makeAdditionComputation(2, 3));
assertEquals(5, result);
}

另一个重要的属性是韧性。一旦写完,一个具备韧性的测试用例,在待测代码的行为和目的没发生变化时,是不需要变化的。增加一个新的行为只需要增加新的测试用例,不用修改老的。上述的第一版测试用例是不具备韧性的,因为只要在构造函数中增加一个新的不想关的参数,就需要更新TA(可能还有其他几十个测试用例)。把这些细节移入helper方法中,可以解决这个问题。

翻译自:

https://testing.googleblog.com/2014/03/testing-on-toilet-what-makes-good-test.html