我应该使用不同的方法为相同的行为创建不同的测试吗?

时间:2014-08-16 21:20:02

标签: unit-testing

我有这样的代码:

public class Foo
{
    ...

    public override bool EqualsTo(object obj)
    {
        ...
    }

    public static bool operator==(Foo left, Foo right)
    {
        ...
    }

    public static bool operator!=(Foo left, Foo right)
    {
        ...
    }
}

此代码示例的主要目的是显示类可以有多种方法来执行相同的操作,例如检查对象'平等。因此,方法EqualsTo和运算符==!=仅用于简化。它可以是任何不同的方法集。重点是有多种方法可以获得相同的行为。

我有两种单元测试变体:

变式1:

[TestClass]
public class FooTest
{
    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsEqual()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(1);

        Assert.IsTrue(foo1.EqualsTo(foo2));
        Assert.IsTrue(foo2.EqualsTo(foo1));
        Assert.IsTrue(foo1 == foo2);
        Assert.IsTrue(foo2 == foo1);
        Assert.IsFalse(foo1 != foo2);
        Assert.IsFalse(foo2 != foo1);
    }

    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsNotEqual()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(2);

        Assert.IsFalse(foo1.EqualsTo(foo2));
        Assert.IsFalse(foo2.EqualsTo(foo1));
        Assert.IsTrue(foo1 == foo2);
        Assert.IsTrue(foo2 == foo1);
        Assert.IsTrue(foo1 != foo2);
        Assert.IsTrue(foo2 != foo1);
    }
}

变式2:

[TestClass]
public class FooTest
{
    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsEqualUsingMethod()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(1);

        Assert.IsTrue(foo1.EqualsTo(foo2));
        Assert.IsTrue(foo2.EqualsTo(foo1));
    }

    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsEqualUsingEqualityOperator()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(1);

        Assert.IsTrue(foo1 == foo2);
        Assert.IsTrue(foo2 == foo1);
    }


    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsEqualUsingInequalityOperator()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(1);

        Assert.IsFalse(foo1 != foo2);
        Assert.IsFalse(foo2 != foo1);
    }

    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsNotEqualUsingMethod()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(2);

        Assert.IsFalse(foo1.EqualsTo(foo2));
        Assert.IsFalse(foo2.EqualsTo(foo1));
    }

    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsNotEqualUsingEqualityOperator()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(2);

        Assert.IsTrue(foo1 == foo2);
        Assert.IsTrue(foo2 == foo1);
    }

    [TestMethod]
    public void ShouldCheckEqualityWhenObjectsNotEqualUsingInequalityOperator()
    {
        var foo1 = new Foo(1);
        var foo2 = new Foo(2);

        Assert.IsTrue(foo1 != foo2);
        Assert.IsTrue(foo2 != foo1);
    }
}

对于我来说,变体1更短且易于理解,但变体2在完成的工作和完成方式上更精确,并且具有更多样板代码,例如数据初始化和设置。我想知道这两种变体中哪一种更受欢迎。或者可能有比那些更好的变种。

平等测试仅用于简化,数据设置和初始化可能更长。

另一个例子:

public class Bar
{
    ...
    public int this[short index] { ... }
    public int this[int index] { ... }
    public int this[long index] { ... }
}

我应该为每个索引器创建单独的测试,还是可以在一个测试中为同一个对象测试它们,假设它们的行为应该相同。

1 个答案:

答案 0 :(得分:1)

是的,你应该,而且我也会投票支持你提出意见。

这就是原因。

测试应该只测试一件事。

一件事。

如果你想测试Equals方法是否有效,那就是1次测试。

如果你想测试==运算符是否有效,那就是另一个测试。

有些人可能会认为这两者是相同的,特别是如果其中一种方法调用另一种方法。

因此,我投票以关闭这个问题作为征求意见的问题。

但在我看来,每次测试你应该只测试一件事。如果您有多个方法实现相同的概念,每种方法都需要进行自己的测试。

最后,您希望失败的测试告诉您具体出了什么问题。如果“具体”可以是任何数量的方法,那么您的测试过于宽泛。

但这是我的意见。