单断言单元测试不会违反DRY原理吗?


12

每当我编写单元测试时,我总是试图在每个测试中使用一个断言,以便在测试失败时简化调试。但是,当我遵循这个规则时,我感到我在每个测试中都在不断复制相同的代码,并且通过进行更多的测试,变得更难回头阅读和维护。

那么单断言测试是否违反DRY?

是否有一个很好的规律可循找到了很好的平衡,就像刚有每个方法一个测试?*

*我意识到可能没有一种适合所有需求的解决方案,但是有没有建议的解决方法?


5
您可以将复制的代码提取到方法中
Ismail Badawi 2013年

@IsmailBadawi听起来不错。我认为这些方法应该返回我正在测试的类对象的实例
Korey Hinton 2013年

1
您正在以给定状态创建要测试的东西吗?这听起来像个固定装置。
Dave Hillier

@DaveHillier是的,我今天学了一个新词。谢谢:)
Korey Hinton

取决于您如何解释每个测试1个断言,如果您是指一个Assert *调用,则是,如果您还想确保不变量保持不变(然后再次将其提取到方法中),或者是否有多种效果可以t在一次断言中测试(或者如果您这样做,则不清楚为什么失败)
棘手怪胎

Answers:


14

正确的单元测试具有一个命名约定,可以帮助您立即确定失败的原因:

public void AddNewCustomer_CustomerExists_ThrowsException()

这就是为什么每个测试只有一个断言,以便每种方法(及其名称)都对应于您断言的条件的原因。

正如您正确指出的那样,每个新测试都将具有类似的设置代码。与任何代码一样,您可以将通用代码重构为自己的方法,以减少或消除重复,并使代码更干燥。一些测试框架经过专门设计,可让您将安装代码放在一个地方

在TDD中,没有测试是YAGNI,因为您仅根据代码要求编写测试。如果不需要它,则不会编写测试。


重构为单个方法听起来不错。如果需要类的实例处于某种状态,则可以在重构方法中创建并返回该对象的新实例,或者像您建议的那样,使用测试框架提供的方法进行初始测试设置。
Korey Hinton 2013年

你的最后一点,我敢肯定,我可以写的功能我想测试喜欢的代码都有,而不是功能,它需要
joelb

5

那么单断言测试是否违反DRY?

不可以,但是会助长违规行为。

也就是说,良好的面向对象设计往往会在单元测试中脱颖而出-主要是出于充分的理由。更为重要的是,单元测试之间应相互隔离,以便可以单独测试该测试,并在需要时对其进行修复,以确保您不会破坏其他测试。基本上,测试的正确性和可读性比其大小或可维护性更为重要。

坦率地说,出于您所描述的原因,我从来都不喜欢每个测试规则都使用一个断言:它会导致很多样例代码难以阅读,容易误解样例,并且如果进行重构则很难很好地解决(这会使您减少重构)。

如果一个函数应该为给定的输入返回一个“ foo”和“ bar”的列表,但是以任何顺序使用两个断言来检查它们是否都在结果集中是完全可以的。遇到麻烦的地方是,单个测试正在检查两个输入或两个副作用,而您不知道两个中的哪个导致了故障。

我认为这是对单一责任原则的一种变体:应该只有一件事会导致测试失败,并且在理想情况下,更改只能破坏一个测试。

但是最终这是一个权衡。您是否更有可能花费更多的时间来维护所有复制粘贴代码,还是您会花费更多的时间来寻找可能由多个来源破坏测试的根本原因。只要编写一些测试,就没什么大不了的。尽管我不赞成单项测试,但我倾向于在更多测试方面犯错。你的旅费可能会改变。


1
对于测试,DAMP比DRY(描述性和有意义的短语)更为重要。
约尔格W¯¯米塔格

2

不。这似乎只是您的操作方式。除非您在他们认为这是一个很好的做法的地方找到了值得注意的参考。

使用测试夹具(尽管在XUnit术语中是测试集,但设置和拆卸是夹具),即,一些设置或示例适用于所有测试。

使用像通常那样构造代码的方法。重构测试时,通常的TDD Red-Green-Refactor不适用,而应采用“红色重构”。那是,

  1. 故意破坏测试,
  2. 做你的重构
  3. 修正测试

这样,您知道测试仍然会给出正面和负面的结果。

有几种标准测试格式。例如,“ 安排”,“行动”,“断言”或“ 何时给出,然后(BDD)”。考虑为每个步骤使用单独的功能。您应该能够调用该函数来减少样板。

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.