如何在不违反单一职责原则的情况下编写类似的测试用例?

How to write similar test cases without breaking the Single Responsibility Principle?

我为不同的输入创建了一个单元测试,以确保输出正确。

[TestMethod]
    public void CountInversionTest()
    {
        #region Arrange
        int[] sourceArray = {4, 3, 2, 1};
        int correctInversionCount = 6;
        int[] sourceArray2 = { 1, 3, 5, 2, 4, 6};
        int correctInversionCount2 = 3;
        int[] sourceArray3 = { 5, 6, 2, 3, 1, 4, 7 };
        int correctInversionCount3 = 10;
        #endregion

        #region Act
        Sorter sorter = new Sorter();
        int inversionCount = sorter.CountInversion(sourceArray);
        int inversionCount2 = sorter.CountInversion(sourceArray2);
        int inversionCount3 = sorter.CountInversion(sourceArray3);
        #endregion

        #region Assert
        Assert.AreEqual(correctInversionCount, inversionCount);
        Assert.AreEqual(correctInversionCount2, inversionCount2);
        Assert.AreEqual(correctInversionCount3, inversionCount3);
        #endregion
    }

因为案例非常相似,所以我把它们放在一个测试方法中。这种行为是正确的还是违反了单一职责原则?如果它破坏了 SRP,什么是更好的解决方案?

单一职责原则告诉我们,这个方法应该只有一个改变的理由。因此,单元测试应该测试一种方法,并且只应在被测方法更改时更改。这就是 CountInversion() 方法。 CountInversion() 方法是否会以 sourceArray 输入之一必须更改但其他输入必须更改的方式进行更改?在这种情况下,应将输入分成单独的测试以适应 SRP。

一般情况下,一个单元测试多次调用不同输入的被测方法是可以的。正如 @itsme86 评论的那样,测试框架通常通过将参数传递给单元测试来促进此类行为。

使用像 xUnit.net, you could write a Parameterized Test 这样的适当的单元测试框架来代替:

[Theory]
[InlineData(new[] { 4, 3, 2, 1 }, 6)]
[InlineData(new[] { 1, 3, 5, 2, 4, 6 }, 3)]
[InlineData(new[] { 5, 6, 2, 3, 1, 4, 7 }, 10)]
public void ParameterizedCountInversionTest(int[] input, int expected)
{
    Sorter sut = new Sorter();
    var actual = sut.CountInversion(input);
    Assert.Equal(expected, actual);
}

这将 运行 三个测试,而不是一个,让您更好地了解哪个特定测试用例失败(如果有任何失败)。

这样的测试也更具可读性。

NUnit也有这个功能,但是MSTest没有(我上次看的)。

我决定回答我自己的问题

所以我没有使用任何第三方框架或库进行测试,而是使用默认的 MSTest。 我最终这样做了

    [TestMethod]
    public void CountInversionTestCase1()
    {
        CountInversionTest(new int[] { 4, 3, 2, 1 }, 6);
    }
    [TestMethod]
    public void CountInversionTestCase2()
    {
        CountInversionTest(new int[] { 1, 3, 5, 2, 4, 6 }, 3);
    }
    [TestMethod]
    public void CountInversionTestCase3()
    {
        CountInversionTest(new int[] { 5, 6, 2, 3, 1, 4, 7 }, 10);
    }

    public void CountInversionTest(int[] sourceArray, int expectedInversionCount)
    {
        #region Act
        Sorter sorter = new Sorter();
        long actualInversionCount = sorter.CountInversion(sourceArray);
        #endregion

        #region Assert
        Assert.AreEqual(expectedInversionCount, actualInversionCount);
        #endregion
    }

这不是最好的解决方案,但它满足要求并且不使用任何第三方库。 我希望它能帮助那里的任何人。