如何在大型C#项目中进行TDD时处理缓慢的单元测试

5
使用Visual Studio 2017,NUnit和Resharper测试运行器,在大型C#项目(5000+个测试)中进行TDD时,如何保持良好的单元测试速度?即使每个测试只需5ms,这也需要25秒,对于TDD循环来说相当慢。
我们的测试不调用数据库,也不调用外部Web服务。它们只测试业务逻辑。
我发现使用Moq,仅执行Mock.Setup()就需要近1ms。由于我们可能会在每个测试中调用几个Moq设置,这是导致我们单元测试缓慢的主要原因。
有没有办法加快单元测试速度?有没有比Moq更快的模拟库?或者有没有更快的测试运行器?

1
5000个测试需要25秒,我认为这相当合理。一种方法是将您的解决方案分解,可能将常见/基础设施事物提取到可重用的NuGet包中。然后总的单元测试时间不会减少,但开发人员通常会逐个处理组件。 - sellotape
我想先说一下,我从来没有做过TDD,但我经常进行单元测试。在我的阅读中,“测试应该快速运行”的印象是,测试不应该花费几个小时,甚至可能不到几分钟的时间来运行。长时间运行的测试会鼓励人们不去运行测试。在我看来,等待25秒并不需要太长时间。 - Kenneth K.
1
你正在使用哪个测试框架?有些支持并行运行测试。 - user247702
这是个好主意,我正在使用Nunit,它支持并行测试,我会试一下的,谢谢! - Chocoman
大多数NUnit运行器也支持仅运行受影响的测试,因此它不应该在每次更改时运行接近5000个测试。对于TDD来说,特别是对于较小的解决方案,NCrunch是一个非常好的工具,因为它会根据测试结果实时地注释您的代码。但需要付费。 - sellotape
2个回答

12
你正在走进一个错误的兔子洞:所有单元测试的总运行时间仍然在非常合理的范围内!
在开发过程中(也许使用TDD),你不关心所有的单元测试。你只关心与当前组件/包/...相关的测试!
也就是说:当你在文件A中进行更改时,你可能想要(手动)运行A目录下的所有单元测试。你再进行一些小的更改,再次运行这些测试。
之后,当你认为:“现在我完成了”,那么你会调用所有的单元测试,以确保你没有通过重新布置此处的房间家具而在建筑物的另一端破坏了某些东西。
所以,答案是:你还好,别担心。
我们有5000多个Java单元测试。在我们最快的构建服务器上,执行它们大约需要10分钟。但这还可以接受。因为当我决定我的更改集已经完成并将其推送到服务器时,构建服务器才会开始工作,20分钟后返回“损坏”或“全部正常”。当这25秒成为问题时,通常是因为您手动触发了所有测试,过于频繁地运行它们。现在,更好的做法是花费精力找到聪明的方法,以高效的方式仅在解决特定问题时运行相关的测试。(在Java中使用JUnit很容易:我点击当前包,并选择“在此处运行所有测试”)

如果您使用Visual Studio的企业SKU,则可以为您正在工作的代码区域启用实时单元测试功能,以仅测试您正在处理的内容。NCrunch(如上面的评论中提到的)是另一个类似的工具。 - Terje Sandstrøm

0

考虑减少大部分测试。

虽然我没有很多单元测试和TDD的经验,但是我有限的经验表明,大多数单元测试都是相当无用的。而且有经验的人支持我的观点,例如这两篇文章:

我不确定这个讨论的连续性(即谁是第一个提出它的人),但有几个人引用了上面的文章并同意它,也许还加入了他们自己的一些观点:

请注意,这个参数并不是关于测试的问题,而是关于广泛的单元测试与集成和系统级测试的区别。

1
第一篇文章非常有争议。人们可以争论编写某些类型的单元测试的成本是否超过了其收益,但你的开头陈述太过宽泛,不正确。 - user247702
@Stijn 当然这是有争议的,如果这个想法被广泛认为是真理,每个人都会遵循它。此外,没有一篇文章主张禁止单元测试,只是停止编写成千上万个单元测试,并将重点放在集成和系统测试上。 - Misamoto
通过集成测试和系统测试,您可以看到您的代码是否正常工作,但是找出代码错误所在的位置非常困难。单元测试可以告诉您非常具体的不工作部分,并回答“where”的部分。因此,您需要两者,然后 @ghostcat 的答案非常好。只测试您需要的内容,但保留所有测试,它们是您的回归套件。 - Terje Sandstrøm
@TerjeSandstrøm 不完全是这样。 "干净" 的单元测试会模拟依赖项,因此如果类 A 在特定参数下运行良好,类 B 在特定参数下也运行良好,并不意味着它们相交的地方在使用相同参数时也能正常工作。由于设计上单元测试不包含类 A 中的类 B,也不包含类 B 中的类 A,只有模拟对象,因此无法捕获相交错误。 - Misamoto
“Clean”的单元测试不一定需要模拟依赖项。请参阅TDD的经典方法与Mockist方法之间的区别。对此存在很多争议。 - Chocoman

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