Let’s assume you have several JUnit tests in a test class. That class contains some tests, part of them are very stable but others are not.

import org.junit.Test;

public class JUnitRetryExampleTest {

    @Test
    public void stableTest() {
        // some test code
    }

    @Test
    public void unstableTest() {
        //  some test code
    }

}

To implemplement the JUnit retry logic for failed tests we have to create an annotation @Retry and implement TestRule interface (RetryRule).

Retry annotation

@Retry annotation allows us to mark the JUnit tests that we want to apply the retry logic to.

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {}

Junit Retry Rule

RetryRule actually implements the retry logic in JUnit.

import java.util.concurrent.atomic.AtomicInteger;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class RetryRule implements TestRule {

    private AtomicInteger count;

    public RetryRule(int count){
        super();
        this.count = new AtomicInteger(count);
    }

    @Override
    public Statement apply(final Statement statement, final Description desc) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                while (count.getAndDecrement() > 0) {
                    try {
                        statement.evaluate();
                        return;
                    } catch (Throwable throwable) {
                        if (count.get() > 0 && desc.getAnnotation(Retry.class)!= null) {
                            System.out.println("!!!================================!!!");
                            System.out.println(desc.getDisplayName() + "failed");
                            System.out.println(count.toString() + " retries remain");
                            System.out.println("!!!================================!!!");
                        } else {
                            throw throwable;
                        }
                    }
                }
            }
        };
    }
}

Annotate JUnit tests with @Retry

Now you need to define how many times we should run tests if they failed and mark tests that we want to use the retry logic for. In this example we set the number of retries to 2: RetryRule retryRule = new RetryRule(2)

public class JUnitRetryExampleTest {

    @Rule
    public RetryRule retryRule = new RetryRule(2);

    @Test
    public void stableTest() {
        // some test code
    }

    @Test
    @Retry
    public void unstableTest() {
        //  some test code
    }

}

You may also find these posts interesting: