C# 可以复印吗&;逻辑基本相同时粘贴单元测试?
我现在有10个测试,只要我的俄罗斯方块在路上或墙上有一块,它就不会向左移动。现在,我必须为正确的运动测试同样的行为C# 可以复印吗&;逻辑基本相同时粘贴单元测试?,c#,java,unit-testing,tdd,C#,Java,Unit Testing,Tdd,我现在有10个测试,只要我的俄罗斯方块在路上或墙上有一块,它就不会向左移动。现在,我必须为正确的运动测试同样的行为 如果我只是复制我已经为左移做的10个测试,只做所需的更改,对代码本身也做同样的更改,这是否太糟糕了?或者,我是否应该再次从一开始就进行每个测试,即使逻辑基本相同?尝试采用您没有提到的第三种方法,即重构代码,以便您可以在所有10个测试之间共享一个测试实现 jist是,复制代码几乎总是错误的。在本例中,您可以将检查代码重构为一个名为的方法,例如istetrispieceUnableto
如果我只是复制我已经为左移做的10个测试,只做所需的更改,对代码本身也做同样的更改,这是否太糟糕了?或者,我是否应该再次从一开始就进行每个测试,即使逻辑基本相同?尝试采用您没有提到的第三种方法,即重构代码,以便您可以在所有10个测试之间共享一个测试实现
jist是,复制代码几乎总是错误的。在本例中,您可以将检查代码重构为一个名为的方法,例如
istetrispieceUnabletoveleftbecauseofapeceorawall
。在为单元测试编写一些“共享”功能时,我总是使用非常描述性的方法名称,因为它非常清楚正在做什么/测试什么。测试代码与任何其他代码一样,应该进行维护和重构
这意味着,如果您有共享逻辑,请将其提取到自己的函数中
某些单元测试库(如xUnit系列)对于此类共享代码具有特定的测试夹具、设置和拆卸属性
请参阅相关问题-“为什么复制粘贴代码很危险?”。复制粘贴没有错,这是一个很好的开始。事实上,它比从头开始要好,因为如果您有工作代码(无论是测试还是其他),那么复制粘贴比从头开始更可靠,也更快
然而,这只是第一步。第2步是重构通用性,第1步只是帮助您了解通用性。如果您已经可以在不复制的情况下清楚地看到它(有时先复制然后检查比较容易,有时不容易,这取决于执行此操作的人员),则跳过步骤1。如果您重复代码,则必须重构。您的情况是一个常见问题,可通过“参数测试”解决。当测试线束支持时,参数测试允许将多组输入值作为参数传递。您可能还想查看模糊测试,我发现它在这种情况下很有用。我对此有点争议。虽然在生产代码中必须尽可能避免代码重复,但这对于测试代码来说并不坏。生产和测试代码的性质和意图不同:
- 生产代码可以承受一定的复杂性,以便于理解/维护。您希望代码处于正确的抽象级别,并且设计保持一致。这是可以的,因为你有测试,你可以确保它的工作。如果您在逻辑级别的代码覆盖率达到100%,那么生产代码中的代码重复就不会成为问题。这真的很难实现,所以规则是:避免重复并最大化代码覆盖率
- 另一方面,测试代码必须尽可能简单。您必须确保测试代码实际测试了它应该测试的内容。如果测试很复杂,您可能会在测试中遇到bug或错误的测试——并且您没有针对测试的测试,因此规则是:保持简单。如果测试代码是重复的,当它发生变化时,这并不是什么大问题。如果仅在一个测试中应用更改,则在修复该更改之前,另一个测试将失败
PS:如果您真的不同意,请留下评论。请记住,您的测试是针对您的代码的。如果您发现除了左/右之类的东西之外,您的测试看起来是重复的,那么可能存在一些左/右重复的底层代码。因此,您可能想看看是否可以重构代码以使用left或right,并向其发送left或right标志。xunitpatterns.org网站说“否”(复制/粘贴不合适),因为当需要更新测试时,这会增加成本:
作者:阿里·范德尔森、利昂·莫宁、亚历克斯·范登伯格、杰拉德·科克我同意@Rob。代码需要重构。但是如果此时不想重构代码,那么可以进行参数化测试。不同参数的相同测试运行。请参阅nunit中的
TestCase
和TestCaseSource
属性
提及
我有时发现自己进行非常复杂的单元测试只是为了避免测试代码重复。我认为这样做不好。任何单个单元测试都应该尽可能简单。如果你需要复制来实现它,那就让它去吧 另一方面,如果您的单元测试有+100500行代码,那么显然应该对其进行重构,这将是一种简化
当然,试着避免无意义的单元测试重复,比如测试1+1=2,2+2=4,3+3=6。如果您真的需要在不同的数据上测试相同的方法,请编写数据驱动测试。+1,我觉得您的论点很有说服力。也许我们可以说,如果您的代码具有x级复杂性,那么它需要进行测试。这适用于测试