【问题标题】:Multiple arrangements/asserts per unit test?每个单元测试有多个安排/断言?
【发布时间】:2010-05-17 19:26:43
【问题描述】:

我们中的一群人(.NET 开发人员)正在谈论单元测试。不是任何一个框架(我们已经提到了 MSpec、NUint、MSTest、RhinoMocks、TypeMock 等)——我们只是在谈论一般性。

我们看到许多语法强制每个场景进行不同的单元测试,但我们没有看到一种途径来重新使用具有各种输入或场景的单元测试。此外,我们看不到在给定测试中进行多个断言的途径,而早期断言的失败会威胁到以后断言的测试(在同一个测试中)。

今天在 .NET 单元测试(基于状态或行为)中是否发生过类似的事情?

【问题讨论】:

  • “但我们没有看到一种途径来重新使用具有各种输入或场景的单元测试”TestCases 不是一个类吗?你不能对它们进行子类化吗?我不明白这个问题。你能举例说明你被阻止做什么吗?
  • 回复:您的报价,我们想知道是否可以有一个输入列表,这些输入都将通过一个测试进行测试。我刚刚用谷歌搜索了 NUnit 的 RowTest 扩展(不知道 MSTest、MSpec 等是否有类似的东西)。这看起来只使用值类型。对于更复杂的类型,我很乐意看到类似的东西,但我只是不知道我期望它是什么样子(从语法/等角度来看)。
  • @lance:什么? TestCase 是一个类。您将其子类化以重用代码。为什么不简单地将 TestCase 子类化以重用代码?对 TestCase 进行子类化与“仅值类型”和“更复杂的类型”有什么关系?
  • 查看 SumTest() (codeclimber.net.nz/archive/2008/01/18/…)。这是一项测试,根据您提供的输入数量执行多次。作为一名开发人员,我对使用这种方法(我刚刚发现)的体验并不感到兴奋,但它/is/“重新使用具有各种输入的单元测试”。
  • @lance:你为什么创建你的TestCase的子类?

标签: .net unit-testing assert


【解决方案1】:

查看 NUnit 中的 [TestCase(params)] 允许使用不同的输入进行相同的测试。

另外,对于多个断言的事情, 查看 OAPT(每个测试一个断言)运行器 - 它承诺使用多个断言进行测试并将每个断言作为自己的测试运行: http://rauchy.net/oapt/

【讨论】:

  • 我知道这是很久以前的事了,但上面的链接是死链接罗伊,谢谢
【解决方案2】:

我们没有看到通过各种输入或场景重用一个单元测试的途径。

“标准”设置/拆卸方法已经在很大程度上帮助重用测试代码。最重要的是,我相信许多 .Net 单元测试框架实现了与 Java 对应的 JUnit 和 TestNG 相同或相似的特性,它们支持例如参数化测试。

此外,我们看不到在给定测试中进行多个断言的途径,而早期断言的失败会威胁到以后断言的测试(在同一个测试中)。

在我的解释中,测试方法测试单个用例。如果断言失败,则该测试失败,并且有充分的理由尽快修复它。单元测试的正常状态应该是 100% 成功,在这种情况下,所有测试中的所有断言都会通过。换句话说,失败的测试应该是例外而不是常态。而且我倾向于不太担心特殊情况。如果您仍然担心,您可以随时安排您的测试方法,使其每个只包含一个断言。

【讨论】:

    【解决方案3】:

    我们看到许多语法强制每个场景进行不同的单元测试,但我们没有看到一种途径来重新使用具有各种输入或场景的单元测试。

    使用 MBUnit 中的 RowTest 或 xUnit.net 中的 Theories 来改变输入变量是很常见的。谷歌其中之一,你会发现几个例子。 Ben Hall 有一篇关于在 xUnit.net 中使用 Theory 的精彩帖子:http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html

    此外,我们没有看到在给定测试中进行多个断言的途径,而早期断言的失败会威胁到以后断言的测试

    在一个测试中拥有多个断言很好(并且很常见)。这里需要遵循的概念是单个单元测试应该测试特定行为或单个代码单元。如果您在一个单元测试中有 3 个断言,而第一个失败,那么此时其他 2 个是否通过并不重要(并且大多数测试运行器在一个测试失败后不会在单个测试中运行其余的断言) ,重要的是一个失败的断言。

    对于每个测试是否应该测试多个行为/代码单元,有很多意见。出于多种原因,我更喜欢每次测试的一种行为。最重要的是,当其中一项测试失败时,我或其他人将不得不返回并阅读测试以确切了解失败的原因和原因。如果我们必须通读一个不仅仅是测试单个行为的单元测试,那么我们就是在浪费时间。在以较小的块进行测试时,确保为代码编写正确的测试也容易得多。我强烈建议您获取一份 Roy Osherove 的 The Art of Unit Testing 的副本。

    【讨论】:

      【解决方案4】:

      您可以做的一个解决方案是将场景放入 SetUp 函数中。

      在 NUnit 中,您可以使用如下方法:

      私有类1 c1;

      [SetUp()]
      private void Setup()
      {
      c1 = new class1{Prop1 = 'A', Prop2= 'B'};
      }
      

      然后有两个测试:

      [Test()]
      private void Property1_Is_A
      {
         Assert.AreEqual('A', c1.Prop1);
      }
      
      [Test()]
      private void Property2_Is_B
      {
         Assert.AreEqual('B', c1.Prop2);
      }
      

      每次执行测试之前都会调用 SetUp。我想你可以用一个会被调用一次的构造函数做类似的事情。

      也就是说,有一些很好的论据反对这一点,因为单独的测试应该设置它需要的一切。但这些并不是一成不变的规则。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多