当逻辑基本相同时,复制和粘贴单元测试是否可以?

dev*_*ium 20 c# java tdd unit-testing

我目前有10个测试,只要路径或墙上有一块,我的俄罗斯方块片就不会向左移动.现在,我将不得不为正确的运动测试相同的行为.

如果我只是复制我已经拥有的左移动的10个测试并且只进行所需的更改并对代码本身也做同样的事情,这太糟糕了吗?或者,如果逻辑基本相同,我应该从头开始再进行每次测试吗?

Rob*_*Rob 30

尝试采用您未提及的第3种方法,即重构代码,以便您可以在所有10个测试之间共享测试的一个实现.

问题是,复制代码几乎总是错误的.在此示例中,您可以将检查代码重构为一个名为的方法IsTetrisPieceUnableToMoveLeftBecauseOfAPieceOrAWall.在为单元测试编写一些"共享"功能时,我总是寻找非常具有描述性的方法名称,因为它使得它非常清楚正在进行/测试的内容.

  • `Is_Tetris_piece_unable_to_move_left_because_of_a_piece_or_a_wall` (4认同)
  • @Inverse,当然,如果下划线为你做了=) (4认同)
  • 感谢上帝的自动完成. (2认同)

ewe*_*nli 27

我对这个问题有一点争议.虽然在生产代码中必须尽可能避免代码重复,但这对于测试代码来说并不是那么糟糕.生产和测试代码的性质和意图不同:

  • 生产代码可以提供一些复杂性以便可理解/可维护.您希望代码处于正确的抽象级别,并使设计保持一致.这是好的,因为你有测试,你可以确保它的工作.如果您在逻辑级别实际拥有100%的代码覆盖率,则生产代码中的代码重复不会成为问题.这实际上很难实现,因此规则是:避免重复并最大化代码覆盖率.

  • 另一方面,测试代码必须尽可能简单.您必须确保测试代码实际测试它应该是什么.如果测试很复杂,你可能会在测试或错误测试中遇到错误 - 而且你没有测试测试,所以规则是:保持简单.如果测试代码是重复的,那么当它发生变化时,这不是一个大问题.如果更改仅在一次测试中应用,则另一次测试将失败,直到您修复它为止.

我想说的主要观点是生产和测试代码具有不同的性质.然后它总是一个常识问题,我不是说你不应该考虑测试代码,等等.如果你可以在测试代码中考虑一些因素并且你确定它没问题,那就去做吧.但是对于测试代码,我更喜欢简单而不是优雅,而对于生产代码,我更喜欢优雅而不是简单.最佳的当然是拥有一个简单,优雅的解决方案:)

PS:如果你真的不同意,请发表评论.

  • @PK实际上,复制代码在大多数情况下更容易理解,因为它的复杂性很低(抽象性较低).所以维护并不难,但可能有点重复.在软件工程中,大部分时间都花费*理解*需要做什么,而不是*做*它.如果维持测试是重复和无聊的,那就没问题了.重复的问题是害怕不在所有地方更新逻辑.您不能冒生产代码的风险留下不连贯的不连贯性,但在测试代码中,测试将失败,直到您更改它. (2认同)

Ode*_*ded 14

测试代码与任何其他代码一样,应该进行维护和重构.

这意味着如果您有共享逻辑,则将其提取到自己的函数中.

某些单元测试库(如xUnit系列)具有此类共享代码的特定测试夹具,设置和拆卸属性.

看到这个相关的问题 - "为什么复制粘贴代码很危险?".


Jon*_*nna 8

复制粘贴没有问题,这是一个很好的起点.事实上,它比从头开始更好,就好像你有工作代码(无论是测试还是其他),然后复制粘贴比从头开始更可靠,也更快.

然而,这只是第1步.第2步是重构共性,第1步只是为了帮助你看到这种共性.如果您已经可以在没有复制的情况下清楚地看到它(有时它更容易先复制然后检查,有时它不是,并且它取决于执行此操作的人),然后跳过步骤1.