VS 单元测试未将预期结果和实际结果视为相等

VS Unit Test Doesn't See Expected and Actual Results as Equal

我们在不久的将来将在工作中转向 TDD 开发风格,因此我正在试用 VS 2013 附带的 VS 单元测试(这是我们在工作中使用的)。我正在尝试使用 TDD 编写一个 class 来查找 Kaprekar 常数。我正处于开发阶段,我有一个提交有效数字的测试,我希望返回一个包含一个元素的列表。该元素将由一个 3 元胞数组组成。这三个单元格将包含原始数字、一个数字按降序排列的数字和一个数字按升序排列的数字。我的调试代码显示我得到了预期的结果,但单元测试说我没有。我需要做什么才能让单元测试看到预期结果和实际结果相同?这是我的代码的删节版本。

单元测试代码:

namespace KaprekarsConstantTest
{
[TestClass]
public class UnitTest1
{
    private Kaprekar k;

    [TestInitialize]
    public void Init()
    {
        k = new Kaprekar();
    }

    [TestMethod]
    public void FirstRow()
    {
        int[] row = new int[3];
        row[0] = 5324;
        row[1] = 5423;
        row[2] = 2345;
        List<int[]> expected = new List<int[]>();
        expected.Add(row);
        List<int[]> actual = k.Generate(5324);
        int[] rslt = actual[0];
        int[] expct = expected[0];
        CollectionAssert.AreEqual(expected, actual,
            "\nExpect: " + expct[0].ToString() + "; " + expct[1].ToString() + "; " + expct[2].ToString() +
            "\nActual: " + rslt[0].ToString() + "; " + rslt[1].ToString() + "; " + rslt[2].ToString() + "\n");
    }
  }
}

申请代码

namespace KaprekarsConstant
{
public class Kaprekar
{
    public List<int[]> Generate(params int[] orgNum)
    {
        List<int[]> rtnVal = new List<int[]>();
        int num = orgNum[0];
        string digits = num.ToString();
        int[] row = new int[3];
        row[0] = num;
        List<int> lstDigits = new List<int>();
        string snglNum = String.Empty;
        for (int ndx = 0; ndx < 4; ndx++)
        {
            snglNum = digits[ndx].ToString();
            lstDigits.Add(int.Parse(snglNum));
        }
        lstDigits.Sort();
        string dNum = String.Empty;
        for (int ndx = 3; ndx > -1; ndx--)
            dNum = dNum + lstDigits[ndx].ToString();
        row[1] = int.Parse(dNum);
        string aNum = String.Empty;
        for (int ndx = 0; ndx < 4; ndx++)
            aNum = aNum + lstDigits[ndx].ToString();
        row[2] = int.Parse(aNum);
        rtnVal.Add(row);
        return rtnVal;
    }
  }
}

测试结果

测试名称:第一行

测试全名: KaprekarsConstantTest。UnitTest1.FirstRow

测试源:* …\Projects\C_Sharp\KaprekarsConstant\KaprekarsConstantTest\UnitTest1.cs:第 51 行

测试结果:失败

测试持续时间: 0:00:00.0033773

结果消息: CollectionAssert.AreEqual 失败。

预计:5324; 5423; 2345

实际:5324; 5432; 2345

(索引 0 处的元素不匹配。)

Result StackTrace: at KaprekarsConstantTest.UnitTest1.FirstRow() in …\Projects\C_Sharp\KaprekarsConstant\KaprekarsConstantTest\UnitTest1.cs:line 61

此测试失败的原因有两个:

  • 每个List的第一个元素(元素0)是三个元素的数组。它们实际上并不匹配——第一个元素的第二个元素是 5423 和 5432。即使你修复了这个,它仍然会失败,因为...

  • 其次,您需要告诉 .NET 对列表的元素进行结构比较,它默认进行对象引用比较 - 即每个 int[] 上的引用相等性大批。

按如下方式更改您的集合断言:

CollectionAssert.AreEqual(
    expected, actual, 
    System.Collections.StructuralComparisons.StructuralComparer,
    "\nExpect: " + ... // omitted for brevity
);

测试将通过。

如果你只是比较数组,测试框架做一个零碎的比较,所以这个测试,例如,会通过:

[TestMethod]
public void WillCompareByElement()
{
    var x = new[] { 3, 2 };
    var y = new[] { 3, 2 };

    CollectionAssert.AreEqual(x, y);
}

循环遍历列表的每个元素并以这种方式进行比较,您可能会得到更清晰的测试失败消息。

此外,您可以考虑使用像 Shouldly 这样的体面的断言库。那么你可以这样写:

expected.ShouldBe(actual);

并得到如下输出:

Message: Test method SOTestEquals.UnitTest1.SecondRow threw exception: 
Shouldly.ShouldAssertException: [[5324, 5423, 2345]]
    should be
[[5324, 5432, 2345]]
    but was not
    difference
[*[5324, 5423, 2345]*]

节省您编写自定义输出的时间。