Java 为什么JUnit在第一次失败之前只运行理论测试用例?

Java 为什么JUnit在第一次失败之前只运行理论测试用例?,java,junit,testng,dataprovider,Java,Junit,Testng,Dataprovider,最近,JUnit中添加了一个新概念(从v4.4开始) 简而言之,您可以使用@Theory注释(而不是@test)标记您的测试方法,使您的测试方法参数化,并声明一个参数数组,在同一类中的某处用@DataPoints注释标记 JUnit将依次通过从@DataPoints检索的参数来运行参数化测试方法。但只有在第一次调用失败之前(由于任何原因) 这个概念似乎与TestNG中的@DataProviders非常相似,但是当我们使用数据提供程序时,所有场景都会运行,尽管它们的执行结果是一样的。它很有用,因为

最近,JUnit中添加了一个新概念(从v4.4开始)

简而言之,您可以使用
@Theory
注释(而不是
@test
)标记您的测试方法,使您的测试方法参数化,并声明一个参数数组,在同一类中的某处用
@DataPoints
注释标记

JUnit将依次通过从
@DataPoints
检索的参数来运行参数化测试方法。但只有在第一次调用失败之前(由于任何原因)

这个概念似乎与TestNG中的
@DataProviders
非常相似,但是当我们使用数据提供程序时,所有场景都会运行,尽管它们的执行结果是一样的。它很有用,因为您可以看到有多少场景有效/无效,并且可以更有效地修复您的程序

所以,我想知道为什么不为每个
@DataPoint
执行
@Theory
-标记的方法?(从Theory runner继承下来并定制一个忽略失败的runner似乎并不难,但为什么我们没有这种开箱即用的行为?)

UPD:我创建了一个容错版本的Theory runner,并使其可供公众访问:


为了将其与standard Theory runner进行比较,请运行StandardTheories BehaviorDemo,然后运行FaultTolerantTheories BehaviorDemo,该文件位于
src/test/…
文件夹下

好吧,这个想法和断言一样,第一次失败会停止测试。这就是参数化理论和非参数化理论之间的区别

Parameterized获取一组数据点,并使用每个数据点运行一组测试方法。理论也是如此,但当第一个断言失败时,理论就失败了

试试看。也许它提供了你想要的

在一次测试中报告多个失败通常是一种迹象 与单元测试应该做的相比,测试做的太多了。 通常这意味着要么测试是真正的 功能/验收/客户测试,如果是单元测试,则 这是一个太大的单元测试

JUnit被设计为在许多小型测试中工作得最好。信息技术 在测试类的单独实例中执行每个测试。信息技术 报告每次测试的失败。共享设置代码在以下情况下最为自然 在测试之间共享。这是一个贯穿JUnit的设计决策, 当您决定报告每个测试的多个失败时,您开始 对抗朱尼特。不建议这样做

长时间的测试是一种设计气味,表明设计的可能性 问题肯特·贝克喜欢在这种情况下说“有一个 有机会了解您的设计。”我们希望 看到一种模式语言围绕这些问题发展,但它没有 然而,它却被写了下来。 资料来源:

要忽略断言失败,还可以使用JUnit错误收集器规则:

ErrorCollector规则允许在测试结束后继续执行测试 发现第一个问题(例如,收集所有不正确的 表中的行,并一次报告所有行)

例如,您可以编写这样的测试

public static class UsesErrorCollectorTwice {
  @Rule
  public ErrorCollector collector= new ErrorCollector();

  @Test
  public void example() {
    String x = [..]
    collector.checkThat(x, not(containsString("a")));
    collector.checkThat(y, containsString("b"));             
  }
}

错误收集器使用hamcrest匹配器。根据你的偏好,这是肯定的还是否定的。

根据理论的定义,如果理论中的一个测试是错误的,那么理论就是错误的。如果您的测试用例不遵循这条规则,那么将它们称为“理论”是错误的。

请参阅upd(我想您可能会发现它很有趣)。IMHO,对于工程目的来说,它不是很有用。运行测试后,您希望尽可能多地了解系统的正确性。再一次,我不认为知道有什么不好,在哪些情况下,在多少情况下,这个理论是错误的。这比只知道理论是错误而不知道任何细节要好得多。假设您将编写小型测试单元,每个测试单元只从一个方面测试您的应用程序。有时,这种检查作为一种理论更容易实现。它不能用于任何目的,因为它基于实用逻辑的基本原理。如果在你看来,它在99%的情况下不适合在某个科目中使用,那就意味着你在理解该科目时遇到了一些问题。