优秀的测试套件可以让人在更改代码时感到安全,从而使工作更为轻松;糟糕的测试套件会让人痛苦不堪,且浪费大量时间。编写好的、可维护的单元测试存在着一些特定规则,可使单元测试质量更高、更具效率。
因为我们测试的是由单个代码单元交付的单个功能,所以测试应该相当短是有意义的。至于具体需要多短就取决于多种因素,但通常不会超过几行代码。
良好的编码实践应用于测试代码的方式与应用于生产代码的方式相同。从实践经验上来说,单元测试中最容易违反的规则之一是“Dont Repeat Yourself”。有些人甚至声称单元测试根本不应该共享任何代码。那是全然的废话。当然,我们希望尽可能保持测试的可读性,但是复制粘贴不是解决方案。
一旦了解了前面的两点,你可能会想要为自己的测试创建一些包含常用代码的基类。如果确实如此,请立马停止!这样的基类就像磁铁一样吸引着各种不相关的共享代码,并且增长非常迅速,直到接管你的项目、迭代、产品……为保证这些不被它逐步侵蚀,务必使用组合方式!
单元测试几乎可以一直运行。出于这个原因,一定要模拟外部依赖项和其他可能会减慢测试速度的东西,这通常是数据库、外部系统或文件操作。同时,不要做得太过——完全隔离被测单元也不是一个好的解决方案。
每当听到有人拥有了95%的可用测试套件,并认为这已经足够好到可以投入生产时,我总是哭笑不得,因为单元测试应该必须保证100%可工作性。只有100%通过测试才意味着一切正常(对于单元,您还需要其他类型的测试)。如果你的单元测试看起来不可靠,请确保找到根本原因并尽快修复它。
在第四条和第五条的基础上,必须要提及的是给测试添加“可忽略”注释,这并不是修复测试套件的方法,反而会使测试套件更加不可靠,因为它并不能避免回归Bug之类的问题。
这一条不是说为你的测试编写测试,而是指进行如突变测试、测试驱动开发或频繁地在代码库中“随机更改东西”这样的实践,以查看是否有测试失败。还可以经常做一些脑力练习,试图找出自己的测试中无法发现的对代码的潜在更改。
尽管我不相信每个项目都应该为测试使用一些花哨的命名约定,但合理的命名能够通过只读失败的测试用例的名称来判断代码的哪一部分被破坏了。
为了实现仅仅通过读取失败测试的名称就可以判断出错误的目标,需要的不仅仅是好的名称。一个测试检查也必须限制一些事情。因此,一个好的单元测试应该只包含一个逻辑断言,即只检查被测试方法的一个输出/副作用。
这是一个元技巧,它涵盖了本文中所有其他技巧以及在这里没有提到的技巧。对待测试要像对待/编写代码一样谨慎。考虑良好的设计原则和指标,如测试代码和生产代码之间的低耦合,以及代码的重复、死代码等。
请记住,一个好的测试套件可以使您在更改和重构代码时感到安全,从而使您的工作更加轻松,而糟糕的测试套件则会使您痛苦不堪,浪费大量的时间,并使代码几乎不可能更改。
以上十个标准不一定需要全部遵循,可根据团队、个人情况进行选择性取舍。
作者:陈琦,资深敏捷测试顾问,作为国内知名项目管理软件——禅道的团队成员,主要负责开源自动化测试管理框架——ZTF的开发工作。拥有十多年的敏捷过程实践经验,现致力于测试自动化和DevOps相关领域的实践和研究。
领取专属 10元无门槛券
私享最新 技术干货