如何重构单元测试?

How do I refactor unit tests?

这最近让我抓狂...

什么是重构?

Code refactoring is the process of restructuring existing computer code – changing the factoring – without changing its external behavior.

我们如何确保在重构​​过程中不会破坏任何东西?

Before refactoring a section of code, a solid set of automatic unit tests is needed. The tests are used to demonstrate that the behavior of the module is correct before the refactoring.

好的好的。但是,如果我在单元测试本身 中发现代码味道 ,我该如何继续?说,一个做太多的测试方法?我如何确保在重构​​单元测试时不会破坏任何东西?

我需要某种元测试吗?一路下来都是单元测试吗?

或者单元测试根本不遵守重构的正常规则?

How do I make sure I don't break anything while refactoring the unit tests?

保留旧测试作为参考。


详细说明:具有良好覆盖率的单元测试在结果中值得它们的权重。您不会因为惊人的程序结构或缺乏重复而保留它们;它们本质上是有用的 input/output 对的数据集。

因此,当 "refactoring" 测试时,真正重要的是使用新集测试的程序显示相同的行为。应该仔细地、手动检查每一个差异,因为可能会发现新的程序错误。

您在重构时也可能不小心减少覆盖率。这很难找到,并且需要专门的覆盖率分析工具。

你不知道你不会破坏任何东西。为了避免 'who will test our tests?' 的问题,您应该使测试尽可能简单,以减少出错的可能性。

重构测试时,您始终可以使用自动重构或其他 'trusted' 方法,例如方法提取等。

您还经常使用现有的测试框架。他们由他们的创造者进行测试。因此,当您开始构建自己的(即使是简单的)框架、复杂的辅助方法等时,您可以随时对其进行测试

根据我的经验,有 two reasons to trust tests:

  • 评论
  • 你已经看到它失败了

这两个都是编写测试时发生的活动。如果您保持测试不可变,您就可以继续信任它们。

每次修改测试时,它的可信度都会降低。

您可以通过重复上述过程在一定程度上缓解该问题:查看对测试的更改,并临时更改被测系统 (SUT),以便您可以看到测试失败 如预期.

修改测试时,保持SUT不变。测试和生产代码相互检查,因此 改变一个,同时保持另一个锁定 是最安全的。

尊重这是一个较旧的 post,它被引用 in a comment on my post about TDD in practice。因此,经过审查,我想投入两分钱。

主要是觉得说的很滑:

Every time you modify a test, it becomes less trustworthy.

我对 修改 这个词有异议。关于 refactoring 诸如 changemodify 等词通常被避免,因为它们具有反义词重构。

如果您修改传统意义上的测试,您引入的更改可能会降低测试的可信度。

但是,如果您修改 重构意义上的测试,那么测试应该不少于值得信赖。

这让我回到最初的问题:

How do I refactor unit tests?

很简单,就像您处理任何其他代码一样 - 孤立地进行。

因此,如果您想重构测试,请不要更改代码,只需更改测试即可。

Do I need test for my tests?

不。 事实上,Kent Beck 在他的 Full Stack Radio interview 中解决了这个确切的问题,他说:

Your code is the test for your tests

Mark Seemann 在 中也注意到了这一点:

Tests and production code keep each other in check, so varying one while keeping the other locked is safest.

最后,与其说是如何重构 tests,还不如说是一般的重构。同样的原则也适用,即重构重组代码 而不改变其外部行为 。如果您不改变外部行为,则不会失去信任。