The easiest (as in least amount of new code required) way to do this is to run the test as a parametrized test (annotate with an @RunWith(Parameterized. class) and add a method to provide 10 empty parameters). That way the framework will run the test 10 times.
@RepeatedTest annotation is used to repeat a test for a specific number of times. The basic syntax of @RepeatedTest is as follows: The annotation @RepeatedTest is used for a test method instead of the annotation @Test. A number is passed as the input parameter of the annotation.
The easiest (as in least amount of new code required) way to do this is to run the test as a parametrized test (annotate with an @RunWith(Parameterized.class)
and add a method to provide 10 empty parameters). That way the framework will run the test 10 times.
This test would need to be the only test in the class, or better put all test methods should need to be run 10 times in the class.
Here is an example:
@RunWith(Parameterized.class)
public class RunTenTimes {
@Parameterized.Parameters
public static Object[][] data() {
return new Object[10][0];
}
public RunTenTimes() {
}
@Test
public void runsTenTimes() {
System.out.println("run");
}
}
With the above, it is possible to even do it with a parameter-less constructor, but I'm not sure if the framework authors intended that, or if that will break in the future.
If you are implementing your own runner, then you could have the runner run the test 10 times. If you are using a third party runner, then with 4.7, you can use the new @Rule
annotation and implement the MethodRule
interface so that it takes the statement and executes it 10 times in a for loop. The current disadvantage of this approach is that @Before
and @After
get run only once. This will likely change in the next version of JUnit (the @Before
will run after the @Rule
), but regardless you will be acting on the same instance of the object (something that isn't true of the Parameterized
runner). This assumes that whatever runner you are running the class with correctly recognizes the @Rule
annotations. That is only the case if it is delegating to the JUnit runners.
If you are running with a custom runner that does not recognize the @Rule
annotation, then you are really stuck with having to write your own runner that delegates appropriately to that Runner and runs it 10 times.
Note that there are other ways to potentially solve this (such as the Theories runner) but they all require a runner. Unfortunately JUnit does not currently support layers of runners. That is a runner that chains other runners.
With IntelliJ, you can do this from the test configuration. Once you open this window, you can choose to run the test any number of times you want,.
when you run the test, intellij will execute all tests you have selected for the number of times you specified.
Example running 624 tests 10 times:
I've found that Spring's repeat annotation is useful for that kind of thing:
@Repeat(value = 10)
Latest (Spring Framework 4.3.11.RELEASE API) doc:
With JUnit 5 I was able to solve this using the @RepeatedTest annotation:
@RepeatedTest(10)
public void testMyCode() {
//your test code goes here
}
Note that @Test
annotation shouldn't be used along with @RepeatedTest
.
Inspired by the following resources:
Create and use a @Repeat
annotation as follows:
public class MyTestClass {
@Rule
public RepeatRule repeatRule = new RepeatRule();
@Test
@Repeat(10)
public void testMyCode() {
//your test code goes here
}
}
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;
}
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;
}
}
Using this solution with @RunWith(PowerMockRunner.class)
, requires updating to Powermock 1.6.5 (which includes a patch).
Anything wrong with:
@Test
void itWorks() {
// stuff
}
@Test
void itWorksRepeatably() {
for (int i = 0; i < 10; i++) {
itWorks();
}
}
Unlike the case where you are testing each of an array of values, you don't particularly care which run failed.
No need to do in configuration or annotation what you can do in code.
This works much easier for me.
public class RepeatTests extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite(RepeatTests.class.getName());
for (int i = 0; i < 10; i++) {
suite.addTestSuite(YourTest.class);
}
return suite;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With