9

I have a unit test that fails sometimes and debugging it is a pain because I don't know why it sometimes fails.

Is there a way inside Eclipse that I can run a JUnit test 5 times or 50 times or something?

Thanks.

bluish
  • 26,356
  • 27
  • 122
  • 180
Thom
  • 14,013
  • 25
  • 105
  • 185

4 Answers4

14

I just found the following solution which doesn't require any additional depedency (Spring is required for one of the answers you got).

Run your test with the Parameterized runner:

@RunWith(Parameterized.class)

Then add the following method to provide a number of empty parameters equals to the number of times you want to run the test:

@Parameterized.Parameters
public static List<Object[]> data() {
    return Arrays.asList(new Object[10][0]);
}

This way you don't even have to write a loop. IntelliJ and eclipse also group the results of every iteration together.

javanna
  • 59,145
  • 14
  • 144
  • 125
8

Have you tried something like this?

@Test
public void runMultipleTests() {
    for (int i = 0; i < 10; i++) {
        myTestMethod();
    }
}
Chris
  • 3,400
  • 1
  • 27
  • 41
4

There is a test decorator for this. See Junit API at http://junit.org/apidocs/junit/extensions/RepeatedTest.html

for example

@Test  
@Repeat(10)  
public void FailRandomlyNeedToKnowWhy() {  
    ....
}
javanna
  • 59,145
  • 14
  • 144
  • 125
RoiG
  • 478
  • 3
  • 11
  • 1
    The `RepeatedTest` decorator comes from JUnit while your code example contains a Spring annotation, isn't it? – javanna Jan 29 '12 at 19:04
2

Inspired on this solution:

Use @Repeat annotation like this:

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

    @Test
    @Repeat(10)
    public void testMyCode() {
        //your test code goes here
    }
}

You'll only need these two classes:

Repeat.java:

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention( RetentionPolicy.RUNTIME )
@Target({ METHOD, ANNOTATION_TYPE })
public @interface Repeat {
    int value() default 1;
}

RepeatRule.java:

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

public class RepeatRule implements TestRule {

    private static class RepeatStatement extends Statement {
        private final Statement statement;
        private final int repeat;    

        public RepeatStatement(Statement statement, int repeat) {
            this.statement = statement;
            this.repeat = repeat;
        }

        @Override
        public void evaluate() throws Throwable {
            for (int i = 0; i < repeat; i++) {
                statement.evaluate();
            }
        }

    }

    @Override
    public Statement apply(Statement statement, Description description) {
        Statement result = statement;
        Repeat repeat = description.getAnnotation(Repeat.class);
        if (repeat != null) {
            int times = repeat.value();
            result = new RepeatStatement(statement, times);
        }
        return result;
    }
}

2016-10-25 Edit: In order to use this solution when using @RunWith(PowerMockRunner.class), update to Powermock 1.6.5 (which includes this patch).

R. Oosterholt
  • 7,720
  • 2
  • 53
  • 77
  • It took me a bit to verify that it was rerunning, but I noticed that the time increased from 6 seconds to 2 minutes for 1 vs 1000 runs. However, it does not actually create a new run for each, which resulted in me removing a timeout rule I had. – StarWind0 Aug 17 '21 at 07:41