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

发布于 2024-12-25 17:12:07 字数 975 浏览 0 评论 0原文

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

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

JUnit 将依次运行参数化测试方法,并依次传递从 @DataPoints 检索到的参数。但仅限于第一次此类调用失败(由于任何原因)。

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

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

UPD:我创建了一个错误 - Theories runner 的宽容版本并可供公众访问:https://github.com/rgorodischer/fault-operative-theories

为了将其与标准 Theories 运行器进行比较,运行 StandardTheoriesBehaviorDemo,然后运行位于 src/test/ 下的 FaultTolerantTheoriesBehaviorDemo ... 文件夹。

Recently a new concept of Theories was added to JUnit (since v4.4).

In a nutshell, you can mark your test method with @Theory annotation (instead of @Test), make your test method parametrized and declare an array of parameters, marked with @DataPoints annotation somewhere in the same class.

JUnit will sequentially run your parametrized test method passing parameters retrieved from @DataPoints one after another. But only until the first such invocation fails (due to any reason).

The concept seems to be very similar to @DataProviders from TestNG, but when we use data providers, all the scenarios are run inspite of their execution results. And it's useful because you can see how many scenarious work/don't work and you can fix your program more effectively.

So, I wonder what's the reason not to execute @Theory-marked method for every @DataPoint? (It appears not so difficult to inherit from Theories runner and make a custom runner which will ignore failures but why don't we have such behaviour out of the box?)

UPD: I have created a fault-tolerant version of Theories runner and made it available for a public access: https://github.com/rgorodischer/fault-tolerant-theories

In order to compare it with the standard Theories runner run StandardTheoriesBehaviorDemo then FaultTolerantTheoriesBehaviorDemo which are placed under src/test/... folder.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲鸠 2025-01-01 17:12:07

在一次测试中报告多个失败通常表明
与单元测试应该做的事情相比,测试做了太多的事情。
通常这意味着测试实际上是一个
功能/验收/客户测试,或者,如果是单元测试,那么它
单元测试太大了。

JUnit 旨在最适合许多小型测试。它
在测试类的单独实例中执行每个测试。它
报告每次测试失败。共享设置代码在以下情况下是最自然的:
测试之间共享。这是一个贯穿 JUnit 的设计决策,
当您决定报告每个测试的多个失败时,您就开始
对抗 JUnit。不建议这样做。

长测试是一种设计味道,表明设计的可能性
问题。肯特·贝克在这种情况下喜欢说“有一个
有机会了解您的设计。”我们希望
看到一种模式语言围绕这些问题而发展,但它还没有
却被写下来了。
来源:http://junit.sourceforge.net/doc/faq/faq.htm #tests_12

要忽略断言失败,您还可以使用 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 Matchers。这是否积极取决于您的喜好。

Reporting multiple failures in a single test is generally a sign that
the test does too much, compared to what a unit test ought to do.
Usually this means either that the test is really a
functional/acceptance/customer test or, if it is a unit test, then it
is too big a unit test.

JUnit is designed to work best with a number of small tests. It
executes each test within a separate instance of the test class. It
reports failure on each test. Shared setup code is most natural when
sharing between tests. This is a design decision that permeates JUnit,
and when you decide to report multiple failures per test, you begin to
fight against JUnit. This is not recommended.

Long tests are a design smell and indicate the likelihood of a design
problem. Kent Beck is fond of saying in this case that "there is an
opportunity to learn something about your design." We would like to
see a pattern language develop around these problems, but it has not
yet been written down.
Source: http://junit.sourceforge.net/doc/faq/faq.htm#tests_12

To ignore assertion failures you can also use a JUnit error collector rule:

The ErrorCollector rule allows execution of a test to continue after
the first problem is found (for example, to collect all the incorrect
rows in a table, and report them all at once)

For example you can write a test like this.

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"));             
  }
}

The error collector uses hamcrest Matchers. Depending on your preferences this is positive or not.

往事随风而去 2025-01-01 17:12:07

AFAIK,这个想法与断言相同,第一次失败会停止测试。这就是参数化和参数化之间的区别。理论。

参数化采用一组数据点并针对每个数据点运行一组测试方法。理论也做了同样的事情,但是当第一个断言失败时就会失败。

尝试查看参数化。也许它提供了你想要的。

AFAIK, the idea is the same as with asserts, the first failure stops the test. This is the difference between Parameterized & Theories.

Parameterized takes a set of data points and runs a set of test methods with each of them. Theories does the same, but fails when the first assert fails.

Try looking at Parameterized. Maybe it provides what you want.

黒涩兲箜 2025-01-01 17:12:07

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

A Theory is wrong if a single test in it is wrong, according to the definition of a Theory. If your test cases don't follow this rule, it would be wrong to call them a "Theory".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文