当逻辑基本相同时,是否可以复制和粘贴单元测试?
我目前有大约10个测试,每当我的俄罗斯方块没有向左移动时,如果路径或墙壁上有一块,我就会进行测试。现在,我将不得不为正确的运动测试相同的行为。
如果我只是复制我已经为左侧移动进行的10个测试,并且只进行所需的更改,并对代码本身也做同样的事情,这是否太糟糕了?或者我应该再次从头开始进行每次测试,即使这样,即使逻辑基本相同?
我目前有大约10个测试,每当我的俄罗斯方块没有向左移动时,如果路径或墙壁上有一块,我就会进行测试。现在,我将不得不为正确的运动测试相同的行为。
如果我只是复制我已经为左侧移动进行的10个测试,并且只进行所需的更改,并对代码本身也做同样的事情,这是否太糟糕了?或者我应该再次从头开始进行每次测试,即使这样,即使逻辑基本相同?
我对这个问题的立场有些争议。虽然在生产代码中必须尽可能避免代码重复,但这对于测试代码来说并不是那么糟糕。生产和测试代码在性质和意图上有所不同:
生产代码可以承受一些复杂性,以便易于理解/维护。您希望代码处于正确的抽象级别,并且设计保持一致。这没关系,因为你有测试,你可以确保它有效。如果你在逻辑级别上真正有100%的代码覆盖率,那么生产代码中的代码重复就不会成为问题。这真的很难实现,所以规则是:避免重复并最大化代码覆盖率。
另一方面,测试代码必须尽可能简单。您必须确保测试代码实际测试它应该测试的内容。如果测试很复杂,你最终可能会在测试中遇到错误或错误的测试 - 而且你没有测试的测试,所以规则是:保持简单。如果测试代码是重复的,那么当它发生变化时,这不是一个大问题。如果仅在一个测试中应用更改,则另一个测试将失败,直到您修复它。
我想说的要点是,生产和测试代码具有不同的性质。然后这总是一个常识问题,我并不是说你不应该考虑测试代码等。如果你能在测试代码中考虑一些东西,并且你确定它没问题,那就去做吧。但对于测试代码,我更喜欢简单而不是优雅,而对于生产代码,我更喜欢优雅而不是简单。最好的当然是有一个简单,优雅的解决方案:)
PS:如果您真的不同意,请发表评论。
尝试采用您未提及的第三种方法,即重构代码,以便您可以在所有 10 个测试之间共享一个测试实现。
关键是,复制代码几乎总是错误的做法。在此示例中,您可以将检查代码重构为名为 的方法,例如 。在为单元测试编写一些“共享”功能时,我总是选择非常具有描述性的方法名称,因为它可以非常清楚地说明正在完成/测试的内容。IsTetrisPieceUnableToMoveLeftBecauseOfAPieceOrAWall