【问题标题】:Advantages of the Constraint Model over the Classic Model in NUnit?NUnit 中约束模型相对于经典模型的优势?
【发布时间】:2010-10-13 13:31:50
【问题描述】:

除了更好的可读性(也许?)和能够使用&| 链接约束之外,约束模型与经典模型相比还有哪些其他优势?

我是经典模型的快乐用户,我正在决定是否值得努力重构旧测试。

【问题讨论】:

    标签: unit-testing nunit


    【解决方案1】:

    我不知道除了可读性之外还有什么其他优点。但这可能是一个很大的优势。我发现只需使用Assert.That( ... ) 开始每个测试,而不是使用少量的 Assert 函数,就可以轻松一百万倍地直观地扫描您的断言,因为您不再需要为函数名称而烦恼,只需查看参数即可。

    在 NUnit 2.4 中,两种语法(类和约束)都使用完全相同的代码。无论哪种方式,幕后都没有优势。除非你真的没有更好的时间利用时间,否则我不会费心重写测试。

    【讨论】:

      【解决方案2】:

      我不得不说我是“经典”模型的粉丝。我发现在大多数情况下更容易制定我的断言,而且我发现它们也更容易阅读。代码中没有任何不必要的内容 - 没有“那个”和“是”,它们听起来很流畅,但不适合 IMO 的可发现性。

      这很可能是由于熟悉程度不亚于其他原因,但我认为值得向您保证,您不是唯一一个认为经典模型完全合理的人 :)

      话虽如此,当使用约束更容易表达某些东西时,使用它是有意义的。当某些条件可以显式通过约束进行测试时尤其如此,但经典模型只使用Assert.IsTrue(condition)。关键在于,对于此类情况,约束可能比经典约束提供更多信息。

      因此,我认为学习基于约束的模型是个好主意,但我不会去转换任何测试,也不会在你找到经典模型更简单或更易读。

      【讨论】:

      • 我很困惑为什么有人要使用一个在测试失败时传达不太精确信息的模型。如果是这种情况,您可以将其发挥到极致,只需将 Assert.IsTrue(...) 用于所有内容:-|
      • @nashwan:我发现当测试失败时,我通常有足够的信息——如果我没有,无论如何也很容易改变测试。所以我宁愿在我正在阅读通过测试的更常见的情况下编写我的代码以提高可读性。 Assert.That(foo, Is.Equal(...)) 的额外冗长并不吸引人。 (同样,虽然许多人讨厌在测试中使用多个断言的想法,但如果它正在测试一个逻辑流程,我可以接受。如果一个测试失败,那几乎总是等同于不止一个失败......)跨度>
      • 我更多地考虑了测试在 IDE 之外失败的问题,即在所有人都出来的 CI 中是测试名称和失败句子。正如我在下面的回答中提到的那样,尽管我已经多次看到开发人员将实际/预期混淆了,这可能会引起混淆。关于这两个模型的可读性,我同意,这在旁观者的眼中非常重要(正如你所提到的)。
      • @nashwan:所以如果它在 CI 中失败,我会添加更多信息并查看它再次失败的地方。如果您试图确保您永远不会需要比第一次测试失败时获得的更多信息,那么您将浪费 99% 的时间。
      【解决方案3】:

      我个人更喜欢约束模型Assert.That 风格,现在才使用。我发现这种较新的风格更具可读性,并且已经确定它不太可能混淆“实际”和“预期”的论点。 (就像你当然可以使用经典模型 Assert.AreEqual 等,我见过很多人这样做。)这显然会导致报告错误结果的测试失败。

      举个例子,不检查 ;-),哪些是正确的?

      Assert.AreEqual(actual, expected);
      Assert.AreEqual(expected, actual);
      

      【讨论】:

      • 我确实发现我自己会不时检查这些参数的预期顺序。但话虽如此,对于AreEqual,这些论点的顺序真的很重要吗?也许Assert.Greater(value1, value2) 是一个更好的例子来说明经典模型中这种潜在的歧义?
      • @DavidRR 是的,顺序很重要。不是测试是否失败(无论如何它都会失败),而是因为它会告诉你它期望的实际值而不是期望值(NUnit 从这些值构造一个句子)。
      【解决方案4】:

      引入断言并将较新的约束模型与经典模型进行比较的NUnit 3 documentation 包括以下示例:

      例如,以下代码必须使用约束模型。那里 不是真正的经典等价物。

      整数 [] 数组 = 新整数 [] { 1, 2, 3 }; Assert.That(array, Has.Exactly(1).EqualTo(3)); Assert.That(array, Has.Exactly(2).GreaterThan(1)); Assert.That(array, Has.Exactly(3).LessThan(100));

      虽然文档指出没有“真正的经典等效”,但可以将经典语法与 LINQ 结合使用来编写我认为等效的测试:

      Assert.AreEqual(1, array.Where(x => x == 3).Count());
      Assert.AreEqual(2, array.Where(x => x > 1).Count());
      Assert.AreEqual(3, array.Where(x => x < 100).Count());
      

      有些人可能得出结论,我从文档中提取的约束模型测试比这些经典模型等效项更具可读性。但这可以说是主观的。


      然而,这还不是全部。更重要的是改进了错误消息,失败的约束模型测试在测试失败时发出。† 例如,考虑这个将失败的经典模型测试:

      int[] array = new int[] { 1, 2, 3 };
      Assert.AreEqual(1, array.Where(x => x == 4).Count());
      

      NUnit 抛出的AssertionException 包含以下“简洁”Message

          Expected: 1
          But was:  0
      

      相比之下,当用新的约束模型语法表达这个测试时:

      Assert.That(array, Has.Exactly(1).EqualTo(4));
      

      ...NUnit 返回Message:

          Expected: exactly one item equal to 4
          But was:  < 1, 2, 3 >
      

      我认为大多数人都会同意,此异常消息比使用 NUnit 的旧经典模型语法生成的异常消息更有帮助。


      非常感谢 @nashwan 帮助我了解约束模型中引入的错误消息的这一重要改进。

      【讨论】:

      • 你说得对,哪个更具可读性是浪费时间,因为它完全是主观的。然而,失败的测试的输出是非常不同的。如果我要测试一个不存在的值 4,则比较输出 - “预期:恰好一个项目 4 - 但是是:”(约束)或“预期:1 但是是:0”(经典的)。约束模型清楚地传达了比经典模型更精确的信息。
      • @nashwan 非常感谢您的反馈!我已将您的示例纳入我的答案。您的示例当然支持这样的论点,即新的约束模型语法确实是对旧经典模型语法的改进。
      • 不客气。事实上,Constraint 模型相对于 Simple 模型在失败时输出消息方面的改进是我很少费心在代码中提供任何消息参数的原因。
      【解决方案5】:

      约束模型相对于经典模型的一个主要好处是,某些断言可以写在一行中,而其中没有真正的经典模型等价物。

      例如,这些约束模型没有真正的经典模型等价物:

      int[] array = new int[] { 1, 2, 3 };
      Assert.That(array, Has.Exactly(1).EqualTo(3));
      Assert.That(array, Has.Exactly(2).GreaterThan(1));
      Assert.That(array, Has.Exactly(3).LessThan(100));
      

      来源可以在here找到。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多