TDD/单元测试 - 打破现有测试是否可行

3
在TDD的重构阶段,一次性破坏多个现有测试是否可以。例如更改类的构造函数并修改使用该类的测试。
测试断言测试代码的行为,但是测试的实现排列/操作实际上是测试代码本身。
我猜为了避免多个测试被破坏,单元测试应该尽可能DRY,意味着如果构造函数发生更改,则只需要进行单个更新(在可能的情况下)。
4个回答

5
理想情况下,您应该尝试将测试的设置代码放在一个公共位置,以便所有测试都可以从“权威来源”请求要测试的某种类型的实例。因此,第一步是重构测试以从共享辅助方法获取实例,而不是自己调用new
然后,您可以重构构造函数以接受更多参数。现在,您只需要修复一个地方即可。
我经常称这个辅助程序为TestDataFactory。它了解对象模型的一些信息,因此您可以向其请求Foo的实例,它会返回一个在大多数字段中具有许多有用测试数据的实例。

虽然我大部分同意@Aaron的观点,但我不会太过担心同时破坏多个测试。最重要的是你能彻底地测试你的代码。确实,建议将代码破坏的地方集中在一个地方进行修改,我也是这样做的,但有时候这会增加不必要的复杂性。 - Will Marcouiller

0
如@Arron已经提到的,第一步是早期重构并将代码移动到一个工厂方法中,用该方法实例化你即将测试的对象。
例如:
var sut = CreateSUT();
var result = sut.MethodUderTest();
Assert.IsTrue(result);

对于更复杂的对象,你可能想考虑使用类似测试数据构建器模式的设计模式。这篇博客很好地描述了这个模式。

0

这种情况经常发生在我身上,无论是构造函数还是其他在多个地方调用的东西。我并不认为这是一件大事,通常我只会纠正任何意外失败的测试,然后继续进行我之前的测试。

有些人已经考虑到了避免这种情况的技术,尤其是针对长时间重构的情况,你不想花几个小时处于不能编译的状态中。例如,可以参考 Joshua Kerievsky 提出的 "Limited Red" 的概念。


0
我同意上面提到的大部分内容,但我的做法通常有所不同。我不喜欢在我当前工作的范围之外打破测试。然而,我也不想基于一些非理性的"代码管理恐惧"来限制我的重构(我认为这样的心理问题会导致更严重的质量问题)。
所以,我通常的做法是添加具有新行为的新代码,并保留旧代码一段时间(将其废弃),只要新功能稳定下来就足够了。然后我一次性处理所有其他测试,确保你仅仅修复它们。
在C#中(以此为例),具有默认值的可选参数可以帮助我很多,否则我只需重载或创建新的构造函数/方法。
这种方式做事能使我更加专注于手头的任务(测试),更重要的是,也让我在重构时更无情。这样重构感觉更自然,更少扰乱。
唯一一个我真正不应用于单元测试的原则是DRY(Don't Repeat Yourself)。我不建议任何人将这种思维方式带入测试世界。DRY往往会导致测试用例变得难以理解。我宁愿在测试中有大量的代码,但易于理解,而不是DRY。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接