我有一个课程,我已经抽象出来,变得可测试并开始陷入一个有趣的困境。这些测试类是否应该嵌套?例如......
public class ValidateCompanyTests
{
public virtual Setup()
{
//setup stuff
}
[TestClass]
public class AndCompanyDoesNotExist : ValidateCompanyTests
{
public override Setup()
{
base.Setup();
//setup specific condition
}
[TestMethod]
public void ShouldReturnFalse()
{
}
[TestMethod]
public void ShouldCreateError()
{
}
[TestMethod]
public void ShouldSaveError()
{
}
}
}
AndCompanyDoesExist的设置几乎相同,但条件更多。
我的问题是,除了明显的方法只是在MSTest打印出来之外,我不确定这是否是“更正确”的做法,或者我应该让每个测试完全隔离。会有很多重复的代码(设置,配置),这就是我做出这个决定的原因,但我想要一些社区意见,想法,想法。
所以把它放在我身上! (这也应该是社区维基吗?)
答案 0 :(得分:4)
我过去在这种方法中遇到的问题是,起初看起来很简单。嵌套上下文很棒,直到达到你的第二级继承。突然之间,你会失去对你的测试生活世界的追踪,除非你潜入3层次的等级,并拍摄大量笔记,绘制地图,施放符文等。
我赞成一种方法,其中设置上下文的机制由测试本身明确指示。每个测试类表示一个上下文,它可以单独设置,也可以通过利用外部帮助程序集来创建所需的对象。这样,我总是能够查看测试初始化方法,并至少看到对该类测试的“世界”的高级描述。
让“帮助者”尽可能地相互利用,但测试设置本身应该像这样的伪代码: Given_a_valid_Customer() .WithValidOrders(2) .WithInvalidOrders(1);
Given_a_valid_Customer应设置客户以及任何所需的子对象,如地址。 .WithValidOrders(2)添加两个有效的命令,包括所需的任何子对象,如LineItems。 最后,.WithInvalidOrders增加了一个订单,但有一些致命缺陷。
重点是设置不会陷入细节之中。什么使订单有效或无效?谁在乎,这不是这个测试的内容。此测试仅关注在几个有效的订单中存在无效订单,这是唯一重要的细节。无效顺序的定义可以在别处定义,然后由多个测试上下文使用。如果关于该定义的某些内容稍后会发生变化,那么它可以在一个辅助方法中“修整”,而不是在数百个单独的测试中。
当我看这个测试时,我知道它的世界在我关心的细节水平上是什么样的。
答案 1 :(得分:1)
如果您的目标是最小化重复的设置代码量,我将使用内部类的继承。 Inhertiance还将为您提供更多的重用灵活性,并使您的测试更容易重构。
答案 2 :(得分:1)
我的个人偏好;我会将共享设置内容分解为实用程序类,并将实际测试完全分开。
这里有很多关于这个主题的讨论; Unit Testing: Self-contained tests vs code duplication (DRY)