您如何编写测试与编写测试一样重要
在上一篇文章中,我假设您应该对代码进行单元测试。
在本文中,我将介绍一些有关如何对代码进行单元测试的提示和指示。
1.一次测试一项
这可能是单元测试要遵循的基准规则。所有类都应单独进行测试。除了mock和stubs,他们不应该依赖其他任何东西。
他们不应该依赖于其他测试的结果。他们应该能够在任何机器上运行。您应该能够拿到单元测试可执行文件,甚至在未连接到Internet的情况下在您母亲的计算机上运行它。
2.遵循AAA规则:安排(Arrange),执行( Act),断言(Assert)
在单元测试方面,AAA代表Arrange,Act,Assert。这是编写单个测试以使其更具可读性和实用性的通用模式。
首先,您要安排。在这一步中,您将设置要测试的东西。您设置变量,字段和属性以使测试能够运行以及定义预期结果。
然后您采取行动-即,您调用要测试的方法。
最后,您断言——调用测试框架来验证您的“行为”的结果是否符合预期。遵循AAA原则,你的测试就会清晰易懂。
3.首先编写简单的“ Fastball-Down-the-Middle”测试
您编写的第一个测试应该是最简单的-愉快路径。它们应该是可以轻松,快速地说明您要编写的功能的组件。
如果您正在编写加法算法,则所编写的早期测试应确保您的代码可以执行2 + 2 =4。然后,一旦这些测试通过,则应开始编写该测试的更复杂的测试(如下所述)。代码的边缘和边界。
4.跨边界测试
单元测试应该测试给定边界的两侧。如果要为日期和时间实用程序进行一些测试,请尝试在午夜之前一秒钟进行测试,之后再进行一秒钟测试。检查日期值0.0。
如果要处理包含矩形的结构,请测试矩形内部和外部的点会发生什么。上方或下方呢?向左还是向右?在上方和右侧?下方和左侧?
跨越边界是您的代码可能会失败或以无法预测的方式执行的地方。
5.如果可以,请测试整个光谱
如果可行,请测试您的功能的所有可能性。如果涉及枚举类型,请使用枚举中的每个项目测试功能。
检查每个可能的字符串或每个整数可能是不切实际的,但是如果可以测试每种可能性,请进行检查。
6.如果可能,覆盖所有代码路径
这也是一个挑战,但是如果您的代码是为测试而设计的,并且您使用了代码覆盖率工具,则可以确保单元测试至少覆盖一次代码的每一行。
如果您选择的语言具有代码覆盖率工具,请与单元测试配合使用。覆盖每个代码路径并不能保证没有任何错误,但是可以肯定地为您提供有关每一行代码状态的有价值的信息。
7.编写测试以发现错误,然后对其进行修复
这是一项强大而有用的技术。如果发现错误,请编写一个测试来发现它。然后,您可以通过调试测试来快速修复该错误。
然后,您将进行出色的回归测试,以确保如果该错误由于任何原因再次出现,您将立即知道。当您在调试器中运行简单,直接的测试时,很容易修复错误。
这里的一个附带好处是您已经“测试了测试”。因为您已经看到测试失败,然后又通过了测试,所以您知道该测试是有效的,因为它已被证明可以正常工作。这使其成为更好的回归测试。
8.使每个测试独立
测试永远不能相互依赖。如果必须按特定顺序运行测试,则需要更改测试。
相反,您应该正确使用单元测试框架的Setup
和TearDown
功能,以确保每个测试都可以单独运行。
单元测试框架不保证测试将以任何特定顺序运行。如果您的测试依赖于以特定顺序运行的测试,那么您可能会发现自己有些微妙,难以跟踪测试本身中的错误。
确保每个测试独立进行,并且不会出现此问题。
9.清楚地命名测试名称,不要怕长名
当您在每个测试中执行一个断言时,每个测试可能最终变得非常具体。因此,请不要犹豫使用长而完整的测试名称。拥有TestDivisionWhenNumPositiveDenomNegative
比拥有更好DivisionTest3
。
一个长而完整的名称可以让您立即知道哪个测试失败了,以及该测试到底想做什么。长时间命名的测试也可以记录您的测试。
例如,一个名为的测试DivisionByZeroShouldThrowException
准确记录了当您尝试除以零时代码的作用。
10.测试是否引发了每个引发的异常
如果您的代码引发异常,请编写测试以确保引发的每个异常都在应有的情况下引发。
大多数xUnit测试框架都可以测试是否引发了异常,因此您应该使用该功能来确保在适当的情况下确实引发了代码引发的每个异常。
11.避免使用Assert.IsTrue
避免检查布尔条件。
例如,不要检查是否两个事物都相等Assert.IsTrue
,Assert.AreEqual
而是使用。为什么?因为这:
Assert.IsTrue(Expected = Actual);
将报告类似的内容Some test failed: Expected True, but the actual result was False
。那什么都没告诉你。而是使用Assert.AreEqual
:
Assert.AreEqual(Expected, Actual)
它将告诉您涉及的实际值,例如,它作为错误消息更有价值。Some test failed: Expected 7, but the actual result was 3
12.不断运行测试
在编写代码时运行测试。您的测试应该运行得很快,即使在进行微小的更改后,您也可以运行它们。
如果您不能在正常的开发过程中运行测试,则出问题了-单元测试应该几乎立即运行。如果不是,则可能是因为您不是孤立运行它们。
13.作为每个自动构建的一部分运行测试
正如您应该在开发过程中进行测试一样,它们也应该是持续集成过程中不可或缺的一部分。测试失败意味着您的构建已损坏。
不要让失败的测试流连忘返-将其视为构建失败并立即修复。
结论
好了,有13种编写有用的单元测试的方法。请记住,除非您正在编写单元测试,否则您的代码将最终难以维护和修复。编写良好,全面的单元测试只是一个巨大的胜利。
翻译自:https://medium.com/better-programming/13-tips-for-writing-useful-unit-tests-ca20706b5368
网友评论