自动验收测试中的代码重用,无需过多的抽象

问题描述 投票:0回答:1

最近,我被聘为团队的一员,其工作重点是为我们公司的3D建模软件编写验收测试套件。我们使用内部C#框架来编写和运行它们,从本质上讲,这相当于对TestBase类进行子类化并覆盖Test()方法,通常所有的设置,测试和拆卸都已完成。

[在编写测试时,我注意到很多代码最终都是我经常重写的样板代码。我一直想尝试提取该代码以使其可重用,并使我的代码成为DRYer,但我一直在努力寻找一种方法,而又不会过度抽象我的测试,因为它们应该是独立的。我尝试了很多方法,但是它们遇到了问题:

  1. 使用继承:最幼稚的解决方案,起初效果很好,可以让我快速编写测试,但遇到了常见的陷阱,即测试类变得过于僵化,无法在表兄弟的子类之间共享我的代码,以及在继承树中混淆的逻辑。例如,我有抽象的RotateVolumeTest和TranslateVolumeTest类,它们都从ModifyVolumeTest继承,但是我很快就会知道要旋转转换体积,所以这将是一个问题。
  2. 通过接口使用合成:这解决了以前方法的许多问题,让我可以灵活地在测试中重用代码,但是却导致很多抽象,看起来像是“类膨胀”。具有IVolumeModifier,ISetsUp等,所有这些都使代码在测试中的实际工作中变得不清楚。
  3. 静态实用程序类中的Helper方法:这非常有用,尤其是对于使用Factory模式来快速生成测试所需的复杂对象时。但是,在其中放置一些我知道实际上不是很通用的方法,感觉有点“棘手”,而是用于需要共享非常特定的代码的一小部分测试。
  4. 使用xUnit.net之类的测试框架或类似的框架通过测试套件中的[SetUp]和[TearDown]方法共享代码,通常都在同一类中:我非常喜欢这种方法,因为它可提供我想要的可重用性,而无需从测试代码中抽象出来,但是我的团队对此并不感兴趣。我试图说明采用类似的框架进行测试的潜在好处,但大家的共识似乎是,在重写我们现有的测试类时,不值得进行重构工作。这是有道理的,我认为我不太可能进一步说服他们,尤其是作为一个相对较新的员工时,所以除非我想使我的测试类与其余代码库有很大不同,否则这是不可能的。
  5. [在需要的地方复制并粘贴代码:这是我们目前使用的方法,以及#3和向TestBase添加方法。我知道对于复制/粘贴编码是否可以用于测试代码(当然不适用于生产代码)存在不同意见,但是我认为使用这种方法从长远来看将使我的测试难以维护或更改,因为如果出现错误,我现在有N个地方需要修复逻辑(已经修复了很多错误,只需要修复一个错误)。

在这一点上,我真的不确定我还有什么其他选择,而是选择#5,因为这会减慢我快速或稳健地编写测试的能力,以便与当前代码库保持一致。非常感谢您的任何想法或意见。

testing design-patterns abstraction code-reuse acceptance-testing
1个回答
0
投票

我个人认为,成功的测试框架最重要的是抽象。使编写测试尽可能容易。对我而言,关键点是您将获得更多测试,并且作者将更多的精力放在他们正在测试的内容上,而不是如何编写测试。我见过的每个不关注抽象的测试框架都以一种以上的方式失败了,最终导致了可维护性的噩梦。

[如果逻辑仅在一个测试类中未在其他任何地方使用,则保留在该测试类中,但如果需要在多个位置进行重构,请稍后重构

我将选择除#5以外的所有选项。

© www.soinside.com 2019 - 2024. All rights reserved.