| 2021-02-10
下面的这个测试写的正确吗?
208: @Test public void testIncrement_existingKey() {
209: assertEquals(9, tally.get("key1"));
210: }
事实上,如果不知道 tally 这个对象是如何准备的,你就根本不可能确认它是否正确:
1: private final Tally tally = new Tally();
2: @Before public void setUp() {
3: tally.increment("key1", 8);
4: tally.increment("key2", 100);
5: tally.increment("key1", 0);
6: tally.increment("key1", 1);
7: }
// 200 lines away
208: @Test public void testIncrement_existingKey() {
209: assertEquals(9, tally.get("key1"));
210: }
上面这段代码存在的问题在于:对 key1
这个值进行断言与对其值的修改之间远隔 200 多行。或者说,原因就隐藏在远离影响的地方。
相反,编写测试时,影响应该能够立即追踪到原因。这就是我们用自然语言说话的方式:“如果你超过了速度限制(原因),你会得到一张交通罚单(效果)。”当我们将这两段代码放在一起,我们就很容易看到发生了什么:
1: private final Tally tally = new Tally();
2: @Test public void testIncrement_newKey() {
3: tally.increment("key", 100);
5: assertEquals(100, tally.get("key"));
6: }
7: @Test public void testIncrement_existingKey() {
8: tally.increment("key", 8);
9: tally.increment("key", 1);
10: assertEquals(9, tally.get("key"));
11: }
12: @Test public void testIncrement_incrementByZeroDoesNothing() {
13: tally.increment("key", 8);
14: tally.increment("key", 0);
15: assertEquals(8, tally.get("key"));
16: }
这种方式可能会需要更多的代码。
每个测试设置自己的输入并验证自己的预期输出。这么做的收益是:可读性更好的代码和更低的维护成本。
发表时间:January 31, 2017
原文作者:Ben Yu