单元测试中的代码质量?


23

在编写单元测试时,是否值得花费额外的时间使代码具有良好的质量和可读性?

在编写测试时,我经常会违反Demeter定律,以加快编写速度并避免使用太多变量。从技术上讲,单元测试不能直接重用-它们严格地与代码绑定,因此我看不出有什么理由要花很多时间在它们上面;他们只需要功能。


5
可读性和可维护性是单元测试的主要重点。
EL Yusubov 2012年

2
测试也是代码!
Grant Palin 2012年

即使它没有交付给客户,它仍然是项目的一部分。相应地对待它。

Answers:


11

就质量和可读性而言,您绝对应该比生产代码更好地照顾单元测试。尝试掌握某些代码的功能时,通常会先看单元测试,而读者在查看测试时应迅速了解所涉及的问题。单元测试也往往会发生很大变化,并且如果它们的设计不可靠,将会破坏很多,这使进行测试的好处无效。

出于这个原因,违反Demeter定律绝对是您的单元测试中的一个问题,还有另外2个我无法想到的问题:

  • 如果您的测试在其“ 安排”或“行为”部分违反了Demeter的定律,则可能表明您的生产代码也这样做了,因为您的单元测试只是代码的另一个使用者,并且可能会在同一代码中调用和操作被测类。任何其他生产代码将执行的方式。

  • 如果您的测试在其断言部分违反了Demeter法则(即,验证了深深嵌套在被测对象的依赖关系图中的某些东西的值),则可能是那些实际上是集成测试而不是单元测试。换句话说,如果您在TestA中断言ABCD等于某物,则可能是您实际上是在测试D和A,而不仅仅是A。

顺便说一句,当你说

为了提高编写速度并且不使用太多变量,我经常打破Demeter定律。

你应该知道写作

var grab = myDependency.Grab;
var something = grab.Something;
var very = something.Very;

very.Deep();

实际上没有比德墨特尔更好

myDependency.Grab.Something.Very.Deep();

如果那是你的意思。


47

花时间编写高质量的单元测试代码绝对是值得的:

  • 他们将需要像其他任何代码一样进行维护。
  • 单元测试是系统文档的最佳来源之一,并且可以说是最可靠的形式。他们应该真正表明:
    • 目的:“预期的行为是什么?”。
    • 用法:“我应该如何使用此API?”。
  • 他们将需要像其他任何代码一样进行调试。

支持临时方法的一个因素是,您的单元测试永远不会成为公共API,因此您不必担心什么接口/等。你正在暴露。


22

是的,这很重要。单元测试应遵循与其他代码相当的标准有多个原因:

  • 每个单元测试还充当测试对象的文档。当测试是全面的并且涵盖尽可能多的极端情况和错误情况时,它们通常可以代替类或函数的注释文档。他们还可以作为新手入门。

  • 单元测试也可能有问题。如果代码编写得当,错误将更加明显。

  • 如果由于某种原因以后您需要拆分一个模块,则可能还需要拆分其单元测试。如果编写的测试具有容易辨别的依存关系,则这样做会更容易。

也就是说,始终存在实用性问题。根据代码的语言和性质,如果不花大量的时间在测试上而不是花在要测试的代码上,就很难编写“干净的”单元测试。在那种情况下,我通常不去测试简单,快速的内容和最关键的功能,而不必担心完整的覆盖范围。每当以后出现错误时,我都会为它编写一个测试,并检查是否可以重构新测试和现有测试以使它们更好。


12

如果您无法阅读单元测试并在下一次失败时找出正在测试的内容,那么您将花费两倍的调试时间(一旦发现了测试内容,并且一次修复了正在测试的代码)

老实说,单元测试应该有预期的结果;做程序 得到实际结果;期望针对易于编写和理解的实际结构类型进行测试


1

测试代码应该和您的生产代码一样受到爱戴。为了提高可读性,甚至更多。如果除您之外的任何人(包括离开代码两周后的您)都应该了解发生了什么,那么您应该使代码清晰易读。

这意味着:

  • 将测试数据的构建提取到构建器类中。
  • 将多重断言提取到单独的断言方法中。
  • 命名时要非常精确。Assert.That(x4, Is.EqualTo(y16*2*SOME_VALUE), ASS_ERR_TXT_56)对大多数读者而言,这几乎没有什么意义。

极端地说,可以编写测试,因此它们几乎像散文一样易于阅读和理解。极端测试人员可能会说,长度超过10行的单元测试是不好的。


1

最重要的实际原因是,每次更改代码时,都要更改单元测试。而且,如果您正在执行TDD,则甚至要先更改单元测试。

在测试中执行以下任一操作:

  • 重复的代码
  • 可读性下降
  • 紧耦合
  • 时间耦合
  • 高圈复杂度(很多依赖项)

当需要更改时,您将需要进行大量工作。

像建议的那样对待测试,最终您会后悔。您甚至可能会得出一个错误的结论,即“ TDD不起作用”。


0

这取决于这些单元测试是否是“临时的”。如果

  1. 测试将被频繁使用;

  2. 开发人员必须使用其他开发人员编写的单元测试;

  3. 大多数测试是通过单元测试完成的

然后应该正确编写测试。如果测试本身存在错误,将很难找到该错误并将其修复,尤其是自编写测试以来已经过去了一段时间。

另一方面,如果这些测试仅由开发人员自己使用,那么我认为还可以。但是,仍然最好编写“可读”代码。正如棘手的怪胎所说,与正确编写测试相比,花费更多的时间来修复测试。


甚至自己- (1)单元测试是从来没有临时(2),即使它们是为你的自我,在一个月内(或更多),你不会记得所有的细节,因此它做正确是很重要的
BЈовић
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.