【发布时间】:2011-03-08 14:47:51
【问题描述】:
我一直都知道,通过单元测试实现最大的代码覆盖率是好。我还听到微软等大公司的开发人员说,他们编写的测试代码行数比可执行代码本身还要多。
现在,真的很棒吗?这似乎不是有时完全浪费时间,这只会使维护变得更加困难?
例如,假设我有一个方法DisplayBooks(),它从数据库中填充书籍列表。产品需求告诉如果店里有一百多本书,只能展示一百本。
所以,对于 TDD,
- 我将首先进行单元测试
BooksLimit(),它将在数据库中保存两百本书,调用DisplayBooks(),然后执行Assert.AreEqual(100, DisplayedBooks.Count)。 - 那我会测试是否失败,
- 然后我将更改
DisplayBooks(),将结果限制设置为 100,然后 - 最后我会重新运行测试看看是否成功。
好吧,直接进入第三步不是更容易,而且根本不做BooksLimit()的单元测试吗?当需求从 100 本书限制到 200 本书限制时,只更改一个字符,而不是更改测试,运行测试以检查它是否失败,更改代码并再次运行测试以检查它是否成功,这不是更敏捷吗?
注意:假设代码已完整记录。否则,有些人可能会说,他们是对的,进行完整的单元测试将有助于理解缺乏文档的代码。事实上,有一个BooksLimit() 单元测试将非常清楚地表明有一个最大数量的书籍可以显示,并且这个最大数量是 100。进入非单元测试代码会更加困难,因为这样可以通过for (int bookIndex = 0; bookIndex < 100; ... 或foreach ... if (count >= 100) break; 实现限制。
【问题讨论】:
-
代码覆盖率参数有时会产生误导。除了“是否调用了一行代码”(我猜它定义了代码覆盖率),您还应该看到“它被调用了多少次”。这将允许您判断您的单元测试是否正在验证所有可能值的代码。
-
我认为只需将函数命名为
DisplayBooksShouldReturn100Books()而不是BooksLimit()就会给它一个明确的存在理由。 -
@Martin - 您的命名约定在什么时候过于具体。如果书籍限制更改为 120 或用户可配置怎么办。您不仅需要更改实际的书籍限制值(例如幻数),而且还需要更改方法名称。分界线在哪里?
-
@Gutz:没有具体的分界线,使用常识。通过为测试函数提供更明确的名称,它们可以更好地传达意图。 Imo 他们应该读起来像句子,即“DisplayBooks() 应该返回 100 本书”。
-
100% 代码覆盖率本身并不是一个足够好的指标:pjohnson.info/working-code/2013/10/24/…
标签: unit-testing documentation tdd code-maintainability