在整个“ 测试气味”目录中,有迹象表明您可能正在测试您的代码,而不是其行为。 即使在最不起眼的单元测试中,首要规则也应该是:
使您的代码执行其工作,然后查看结果。
编写代码及其测试的开发人员在为代码的每一行和每个分支进行测试时,常常会误解这一点。 具有讽刺意味的是,我们经常使用这种精确的指标来衡量单元测试的成功率。
目的不是线路覆盖
测试的目的是练习代码打算容纳的所有场景。 我们应该构造一种情况,其中代码旨在完成工作,执行代码,并寻找结果如预期的重要标志。
这意味着我们不希望看到执行了正确的代码行,而是看到已执行的任何代码的输出都是正确的。
从失败的测试开始比较容易
这样做更容易的原因之一是,您不必对编写的代码分散注意力,而开始测试代码。 另一个是您将注意力集中在代码要回答的问题以及检测到答案的方式上。 反过来,这可以防止诸如追逐龙之类的设计缺陷。
我的测试很好吗?
您将如何检查测试以查看测试实现的迹象,而不是行为?
- 它有模拟吗? 如果是这样,您要在模拟中验证什么?
- 如果您以相同的结果巧妙地更改了算法的确切实现,则测试会中断吗?
- 在结果之后,您是否还有其他断言,检查是否调用了正确的模拟?
- 您是否正在对模拟进行第二,第三甚至第四级通话?
- 您的测试方案是否谈论其名称中的代码?
- 您是否正在测试代码的内部独白或其结果?
模拟疯狂
我见过的许多实现测试都大量使用了模拟。 并不是说模拟是错误的……仅仅是因为它们能够如此有效地进行这种测试,当您跨入测试实现的行列时很难发现。
面包店更真实
测试双重而不是模拟,它提供了您要调用的服务的内存内实现,可以更好地用于将测试返回到行为测试。 即使对某些服务进行泊坞服务,也可以使您的测试比模拟事情更真实,更现实。
总体而言,要平衡。 使用提供内存存根的测试框架是前进的好方法,并且可以将测试与实现分离。 在服务上定义包装器并为其提供经过测试的测试倍数也是不错的选择。
TL; DR
- 首先编写测试
- 如果您不需要编写模拟验证电话
- 考虑假货/测试双打代替模拟
- 专注于可证明的结果,而不是所谓的职能
翻译自: https://www.javacodegeeks.com/2020/02/how-do-i-know-if-im-testing-behaviour.html