【问题标题】:Unit test assertion that is true in several cases在几种情况下为真的单元测试断言
【发布时间】:2012-12-16 05:41:22
【问题描述】:

我正在尝试编写一个单元测试来检查某个结果是否正确。但是,有两个结果被认为是正确的。有没有办法用断言做 OR?我知道我可以做 result = x || result = y 并断言这是真的。但我不想看到真!=假,我想看到结果!= x或y。

我使用的框架是 mstest,但我也愿意听取有关 nunit 的建议。

【问题讨论】:

  • 为什么有两个答案被认为是正确的?听起来你有一个你没有控制的输入,你真的应该有两个测试,一个用于每个预期结果(在它是 only 预期结果的条件下)。跨度>
  • @JoeWhite 例如,如果您正在测试排序算法并且规范中不需要稳定性,那么对于特定输入,可能会认为多个输出是正确的。实现可能是确定性的,但您不知道它将如何实现。在我的情况下,规范不够具体(这可能是真正的问题),所以我必须考虑多个正确的输出。
  • 在这种情况下,我们所做的就是断言我们的代码得到的特定结果。不稳定的排序仍然是确定性的(除非你是多线程的)。如果您稍后更改算法并且您的测试开始失败,您可以看到行为实际上仍然正确,并更新测试。当然,这使它更像是回归测试而不是单元测试;但另一方面,为技术上正确的输出添加测试,但您实际上不会通过您的实现获得,这是 YAGNI。

标签: c# unit-testing nunit mstest


【解决方案1】:

你可以试试Fluent Assertions。这是一组 .NET 扩展方法,可让您更自然地指定预期结果测试。 Fluent Assertions 同时支持 MSTest 和 NUnit,所以以后切换到 nUnit 也没什么大不了的。然后你可以使用以下 sn-p 来表达你的断言:

// Act phase: you get result somehow
var result = 42;

// Assert phase
result.Should().BeOneOf(new [] { 1, 2 } ); 
// in this case you'll be following error:
// Expected value to be one of {1, 41}, but found 42.

【讨论】:

    【解决方案2】:

    NUnit 中有一个很好的基于约束的断言模型。它允许定义复合约束。查看详情here

    在你的情况下,断言可能会写:

    Assert.That(result, Is.EqualTo(1).Or.EqualTo(5));
    

    失败的测试消息将是(例如):
    预计:1 或 5
    但是是:10

    【讨论】:

      【解决方案3】:

      你可以这样做:

      Assert.IsTrue( result == x || result == y );
      

      【讨论】:

        【解决方案4】:

        最简单的选择是只使用Assert.IsTrue,但也传递一个字符串消息以在失败时打印。该字符串可以提供有关现实如何未能达到预期的信息:

        Assert.IsTrue(result == x || result == y, "Result was not x or y");
        

        您也可以轻松地在自定义消息中包含实际值:

        Assert.IsTrue(result == x || result == y, "Result was not x or y, instead it was {0}", result);
        

        或者,您可以将“正确”值存储在 Collection 中,然后使用 CollectionAssert.Contains

        【讨论】:

          【解决方案5】:

          您可以创建您的 Assert 方法,以防实际结果可能匹配两个以上的预期值:

          public void AssertMultipleValues<T>(object actual, params object[] expectedResults)
          {
              Assert.IsInstanceOfType(actual, typeof(T));
          
              bool isExpectedResult = false;
              foreach (object expectedResult in expectedResults)
              {
                  if(actual.Equals(expectedResult))
                  {
                      isExpectedResult = true;
                  }
              }
          
              Assert.IsTrue(isExpectedResult, "The actual object '{0}' was not found in the expected results", actual);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-01-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多