初始化对象以在SetUp中或在测试方法期间进行测试?

han*_*ngy 5 unit-testing

我想知道要测试的对象是否应该是一个字段,因此在SetUp方法中设置(即JUnit,nUnit,MS Test,...).

考虑以下示例(这是带有MsTest的C♯,但对于任何其他语言和测试框架,该想法应该类似):

public class SomeStuff
{
    public string Value { get; private set; }

    public SomeStuff(string value)
    {
        this.Value = value;
    }
}


[TestClass]
public class SomeStuffTestWithSetUp
{
    private string value;
    private SomeStuff someStuff;

    [TestInitialize]
    public void MyTestInitialize()
    {
        this.value = Guid.NewGuid().ToString();
        this.someStuff = new SomeStuff(this.value);
    }

    [TestCleanup]
    public void MyTestCleanup()
    {
        this.someStuff = null;
        this.value = string.Empty;
    }

    [TestMethod]
    public void TestGetValue()
    {
        Assert.AreEqual(this.value, this.someStuff.Value);
    }
}

[TestClass]
public class SomeStuffTestWithoutSetup
{
    [TestMethod]
    public void TestGetValue()
    {
        string value = Guid.NewGuid().ToString();
        SomeStuff someStuff = new SomeStuff(value);
        Assert.AreEqual(value, someStuff.Value);
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,只有一种测试方法,第一个例子太长了,但是有了更多的测试方法,这可能是安全的,相当多的冗余代码.

每种方法的优缺点是什么?有没有"最佳实践"?

Ben*_*man 8

一旦开始初始化字段并且通常在测试方法本身设置测试的上下文,这是一个很滑的斜率.这导致了大量的测试方法和真正无法管理的固定装置,这些装置不能很好地解释自己.

相反,您应该查看BDD样式的命名和测试组织.每个上下文制作一个夹具,而不是每个被测系统一个夹具.然后你的[setup]确实设置了上下文,你的测试可以是简单的单行断言.

当您看到执行此操作的测试输出时,它更容易阅读:

OrderFulfillmentServiceTests.cs

  • with_an_order_from_a_new_customer

    • 它应该从信用服务检查他们的信用
    • 它应该没有折扣
  • 有效的信用检查

    • 它应该减少库存
    • 它应该运送货物
  • 与德克萨斯州或加利福尼亚州的客户

    • 它应该添加适当的销售税
  • 与黄金客户的订单

    • 它不应该检查信用
    • 它应该免费加入加急运输

我们的测试现在是我们系统的非常好的文档.每个"with_an ..."都是一个测试夹具,下面的项目是测试.在这些内容中,您可以设置上下文(类名描述的世界状态),然后测试执行简单的断言,验证方法名称的作用.