java - 如何为套件中的所有测试用例应用 JUnit @Rule

标签 java junit junit4

我正在使用 JUnit 4.10 来运行测试套件,并且我已经按照 Matthew Farwell 在 How to Re-run failed JUnit tests immediately? 中的出色说明实现了“重试失败测试”规则。邮政。我使用以下代码创建了一个类“RetryTestRule”:

public class RetryTestRule implements TestRule {

  private final int retryCount;

  public RetryTestRule(int retryCount) {
    this.retryCount = retryCount;
  }

  @Override
  public Statement apply(Statement base, Description description) {
    return statement(base, description);
  }

  private Statement statement(final Statement base, final Description description) {
    return new Statement() {
      @Override
      public void evaluate() throws Throwable {
        Throwable caughtThrowable = null;

        // retry logic
        for (int i = 0; i < retryCount; i++) {
          try {
            base.evaluate();
            return;
          } catch (Throwable t) {
            caughtThrowable = t;
            System.err.println(description.getDisplayName() + ": run " + (i + 1) + "     failed");
          }
        }
        System.err.println(description.getDisplayName() + ": Giving up after " + retryCount
            + " failures");
        throw caughtThrowable;
      }
    };
  }
}

当在测试用例中使用它作为规则时,它工作得很好,但在套件的每个测试用例中使用 @Rule 符号而不是套件定义中的单个符号似乎不是最佳选择,所以在检查了一下之后我在我的 Suite 类中尝试了新的 @ClassRule 表示法:

@RunWith(Suite.class)
@SuiteClasses({
  UserRegistrationTest.class,
  WebLoginTest.class
})
public class UserSuite {    
  @ClassRule
  public static RetryTestRule retry = new RetryTestRule(2);
}

问题是这没有按预期工作:失败的测试没有被重试。有没有人试过这个并且知道解决方案?非常感谢您的帮助!

最佳答案

@ClassRule 每个类执行一次,而不是每个方法执行一次。要让每个方法执行一次,您需要像现在一样使用 @Rule,或者按照 How to define JUnit method rule in a suite? 的答案进行操作.

要重用现有规则,您可以使用 RunRules 类将规则添加到要运行的规则列表中,如下所示:

public class MyRunner extends BlockJUnit4ClassRunner {
    public MyRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        Description description= describeChild(method);
        if (method.getAnnotation(Ignore.class) != null) {
            notifier.fireTestIgnored(description);
        } else {
            RunRules runRules = new RunRules(methodBlock(method), Arrays.asList(new TestRule[]{new RetryTestRule(3)}), description);
            runLeaf(runRules, description, notifier);
        }
    }
}

这是使用上述答案中的示例。您也可以将这两个答案结合起来以获得更细粒度的控制,例如,如果您的测试中有注释,则创建一个 RetryTestRule。

关于java - 如何为套件中的所有测试用例应用 JUnit @Rule,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9034812/

相关文章:

如果“"Convert this usage of the ternary operator to an "结构”,则/"else"上的 Java Sonar 违规

java - 如何复制图像

java - web服务获取ip地址和端口的方法

java - 如何在对子类进行单元测试时在抽象类中注入(inject)变量?

java - Java 中的单元测试多行字符串

java - 简单的 JUnit 测试 assertTrue(true) 失败

java - 我想在用户输入错误密码后发出警报(验证来自数据库),我需要从 Servlet 生成警报,该怎么做?

java - Mockito:如何模拟 javax.inject.Provider 创建的原型(prototype) bean?

eclipse - 在 Eclipse 中为现有类中的新方法生成 JUnit stub

java - Junit 失败 - 字符串比较中的引号