在单元测试中多个断言是坏的吗?即使链接?

Mic*_*ren 40 c# unit-testing mstest asp.net-mvc-2

在这个单元测试中检查这么多东西有什么问题吗?:

ActualModel = ActualResult.AssertViewRendered()        // check 1
                          .ForView("Index")            // check 2
                          .WithViewData<List<Page>>(); // check 3

CollectionAssert.AreEqual(Expected, ActualModel);      // check 4
Run Code Online (Sandbox Code Playgroud)

此测试的主要目标是验证返回正确的视图(检查2)并且它包含正确的数据(检查4).

我可以通过将其分成多个测试来获得任何收益吗?我一切都是为了做正确的事情,但如果它没有实际价值我就不会分手了.

我对单元测试很陌生,所以请保持温和.

Bev*_*van 30

正如其他人所指出的那样,最好在每个测试中坚持使用一个断言以避免丢失信息 - 如果第一个断言失败,你不知道后面的断言是否也会失败.你必须用较少的信息解决问题 - 这可能(可能会)更难.

一个非常好的参考是Roy Osherove的单元测试艺术 - 如果你想要开始正确的单元测试,你可能会比从这里开始做得更糟.

  • 我发现这本书非常好.它极大地提高了我的单元测试的质量.虽然大多数关于软件开发的书籍非常厚,但这本书包含大约270页.这样就可以很好地加入团队的必读列表.如果你赶时间,罗伊建议你只阅读第7章. (2认同)

Dav*_*uth 12

注意未来读者这个问题及其重复在单元测试中有多个断言是不好的做法吗?有相反的多数意见,所以读他们两个并自己决定.

我的经验是,最有用的测试量不是断言,而是场景 - 也就是说,对于给定的一组初始条件和方法调用应该有一个单元测试,并且断言所需的断言数量很多.预期的最终条件.每个断言进行一次单元测试会导致重复设置或曲折的变通方法以避免重复(例如我最近看到的可怕的深度嵌套的rspec上下文).它还会增加测试次数,从而大大减慢您的套件速度.


Joh*_*n K 8

只要每个断言都有一个唯一且识别失败的消息,你应该是好的并且会回避任何断言轮盘问题,因为不难判断哪个测试失败了.使用常识.

  • 有多个断言的问题不在于告诉哪一个失败 - 在大多数情况下你会得到行号,如果没有别的话.问题是你没有看到以后的测试是否也会失败,所以你最终会得到关于这个bug的更少信息.在某些情况下,这并不重要 - 但在某些情况下(大多数情况下,根据我的经验,在我学习本课程之前)它是. (5认同)
  • *是你没有看到以后的测试是否也会失败*但这是不相关的.您一次修复一个Assert.假设如果第一个Assert失败,下一个也将失败,因为前一个条件不满足也是安全的.在我的测试中,我用Assert替换了大多数'if'语句.除了分支是有效的(几乎从来没有这种情况). (2认同)

Ten*_*giz 7

我发现这个问题有一个不同的论点(至少对我自己而言):

如果他们测试相同的东西,使用多个断言是可以的.

例如,可以这样做:

Assert.IsNotNull(value);
Assert.AreEqual(0, value.Count);
Run Code Online (Sandbox Code Playgroud)

为什么? - 因为这两个断言并没有隐藏测试的意图.如果第一个断言失败,则意味着第二个断言也会失败.事实上,如果我们删除第一个断言,那么当第二个断言为空时,第二个断言失败(带有空引用异常 - !!!)value.如果不是这种情况,那么我们不应该把这两个断言放在一起.

所以,这是错误的:

Assert.IsNotNull(value1);
Assert.IsNotNull(value2);
Run Code Online (Sandbox Code Playgroud)

正如我上面提到的,如果第一个断言失败,则没有关于第二个断言的明确指示 - 我们仍然想知道第二个断言会发生什么(即使第一个断言失败).因此,由于这个原因,这两个断言属于两个不同的单元测试.

结论:如果正确完成,放置一个或多个断言就成了首选问题 - 我们是否希望在测试结果中看到断言异常,或者我们是否希望在特定情况下看到其他一些异常.