且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何立即重新运行失败的JUnit测试?

更新时间:2023-11-19 23:43:40

你可以用 TestRule 。这将为您提供所需的灵活性。 TestRule允许您在测试周围插入逻辑,因此您将实现重试循环:

You can do this with a TestRule. This will give you the flexibility you need. A TestRule allows you to insert logic around the test, so you would implement the retry loop:

public class RetryTest {
    public class Retry implements TestRule {
        private int retryCount;

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

        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;

                    // implement retry logic here
                    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
    public Retry retry = new Retry(3);

    @Test
    public void test1() {
    }

    @Test
    public void test2() {
        Object o = null;
        o.equals("foo");
    }
}

TestRule的核心 base.evaluate(),它会调用您的测试方法。因此,围绕此调用,您将进行重试循环。如果在您的测试方法中抛出异常(断言失败实际上是 AssertionError ),则测试失败,您将重试。

The heart of a TestRule is the base.evaluate(), which calls your test method. So around this call you put a retry loop. If an exception is thrown in your test method (an assertion failure is actually an AssertionError), then the test has failed, and you'll retry.

还有一件事可能有用。您可能只想将此重试逻辑应用于一组测试,在这种情况下,您可以在方法的特定注释的测试上方添加到Retry类中。 描述包含该方法的注释列表。有关这方面的更多信息,请参阅我对如何在每个JUnit @Test方法之前单独运行一些代码,而不使用@RunWith或AOP?

There is one other thing that may be of use. You may only want to apply this retry logic to a set of tests, in which case you can add into the Retry class above a test for a particular annotation on the method. Description contains a list of annotations for the method. For more information about this, see my answer to How to run some code before each JUnit @Test method individually, without using @RunWith nor AOP?.

这是CKuck的建议,您可以定义自己的Runner。您需要扩展 BlockJUnit4ClassRunner 并覆盖runChild()。有关详细信息,请参阅我对如何定义的回答套件中的JUnit方法规则?。此答案详细说明了如何定义如何为Suite中的每个方法运行代码,您必须为其定义自己的Runner。

This is the suggestion of CKuck, you can define your own Runner. You need to extend BlockJUnit4ClassRunner and override runChild(). For more information see my answer to How to define JUnit method rule in a suite?. This answer details how to define how to run code for every method in a Suite, for which you have to define your own Runner.