2.14. Repeated Tests
JUnit Jupiter provides the ability to repeat a test a specified number of times by annotating a method with @RepeatedTest
and specifying the total number of repetitions desired. Each invocation of a repeated test behaves like the execution of a regular @Test
method with full support for the same lifecycle callbacks and extensions.
The following example demonstrates how to declare a test named repeatedTest()
that will be automatically repeated 10 times.
@RepeatedTest(10)
void repeatedTest() {
// ...
}
In addition to specifying the number of repetitions, a custom display name can be configured for each repetition via the name
attribute of the @RepeatedTest
annotation. Furthermore, the display name can be a pattern composed of a combination of static text and dynamic placeholders. The following placeholders are currently supported.
[DisplayName](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.DisplayName.html)
: display name of the@RepeatedTest
method{currentRepetition}
: the current repetition count{totalRepetitions}
: the total number of repetitions
The default display name for a given repetition is generated based on the following pattern: "repetition {currentRepetition} of {totalRepetitions}"
. Thus, the display names for individual repetitions of the previous repeatedTest()
example would be: repetition 1 of 10
, repetition 2 of 10
, etc. If you would like the display name of the @RepeatedTest
method included in the name of each repetition, you can define your own custom pattern or use the predefined RepeatedTest.LONG_DISPLAY_NAME
pattern. The latter is equal to "[DisplayName](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.DisplayName.html) :: repetition {currentRepetition} of {totalRepetitions}"
which results in display names for individual repetitions like repeatedTest() :: repetition 1 of 10
, repeatedTest() :: repetition 2 of 10
, etc.
In order to retrieve information about the current repetition and the total number of repetitions programmatically, a developer can choose to have an instance of RepetitionInfo
injected into a @RepeatedTest
, @BeforeEach
, or @AfterEach
method.
2.14.1. Repeated Test Examples
The RepeatedTestsDemo
class at the end of this section demonstrates several examples of repeated tests.
The repeatedTest()
method is identical to example from the previous section; whereas, repeatedTestWithRepetitionInfo()
demonstrates how to have an instance of RepetitionInfo
injected into a test to access the total number of repetitions for the current repeated test.
The next two methods demonstrate how to include a custom @DisplayName
for the @RepeatedTest
method in the display name of each repetition. customDisplayName()
combines a custom display name with a custom pattern and then uses TestInfo
to verify the format of the generated display name. Repeat!
is the [DisplayName](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.DisplayName.html)
which comes from the @DisplayName
declaration, and 1/1
comes from {currentRepetition}/{totalRepetitions}
. In contrast, customDisplayNameWithLongPattern()
uses the aforementioned predefined RepeatedTest.LONG_DISPLAY_NAME
pattern.
repeatedTestInGerman()
demonstrates the ability to translate display names of repeated tests into foreign languages — in this case German, resulting in names for individual repetitions such as: Wiederholung 1 von 5
, Wiederholung 2 von 5
, etc.
Since the beforeEach()
method is annotated with @BeforeEach
it will get executed before each repetition of each repeated test. By having the TestInfo
and RepetitionInfo
injected into the method, we see that it’s possible to obtain information about the currently executing repeated test. Executing RepeatedTestsDemo
with the INFO
log level enabled results in the following output.
INFO: About to execute repetition 1 of 10 for repeatedTest
INFO: About to execute repetition 2 of 10 for repeatedTest
INFO: About to execute repetition 3 of 10 for repeatedTest
INFO: About to execute repetition 4 of 10 for repeatedTest
INFO: About to execute repetition 5 of 10 for repeatedTest
INFO: About to execute repetition 6 of 10 for repeatedTest
INFO: About to execute repetition 7 of 10 for repeatedTest
INFO: About to execute repetition 8 of 10 for repeatedTest
INFO: About to execute repetition 9 of 10 for repeatedTest
INFO: About to execute repetition 10 of 10 for repeatedTest
INFO: About to execute repetition 1 of 5 for repeatedTestWithRepetitionInfo
INFO: About to execute repetition 2 of 5 for repeatedTestWithRepetitionInfo
INFO: About to execute repetition 3 of 5 for repeatedTestWithRepetitionInfo
INFO: About to execute repetition 4 of 5 for repeatedTestWithRepetitionInfo
INFO: About to execute repetition 5 of 5 for repeatedTestWithRepetitionInfo
INFO: About to execute repetition 1 of 1 for customDisplayName
INFO: About to execute repetition 1 of 1 for customDisplayNameWithLongPattern
INFO: About to execute repetition 1 of 5 for repeatedTestInGerman
INFO: About to execute repetition 2 of 5 for repeatedTestInGerman
INFO: About to execute repetition 3 of 5 for repeatedTestInGerman
INFO: About to execute repetition 4 of 5 for repeatedTestInGerman
INFO: About to execute repetition 5 of 5 for repeatedTestInGerman
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.logging.Logger;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.junit.jupiter.api.TestInfo;
class RepeatedTestsDemo {
private Logger logger = // ...
@BeforeEach
void beforeEach(TestInfo testInfo, RepetitionInfo repetitionInfo) {
int currentRepetition = repetitionInfo.getCurrentRepetition();
int totalRepetitions = repetitionInfo.getTotalRepetitions();
String methodName = testInfo.getTestMethod().get().getName();
logger.info(String.format("About to execute repetition %d of %d for %s", //
currentRepetition, totalRepetitions, methodName));
}
@RepeatedTest(10)
void repeatedTest() {
// ...
}
@RepeatedTest(5)
void repeatedTestWithRepetitionInfo(RepetitionInfo repetitionInfo) {
assertEquals(5, repetitionInfo.getTotalRepetitions());
}
@RepeatedTest(value = 1, name = "{displayName} {currentRepetition}/{totalRepetitions}")
@DisplayName("Repeat!")
void customDisplayName(TestInfo testInfo) {
assertEquals("Repeat! 1/1", testInfo.getDisplayName());
}
@RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME)
@DisplayName("Details...")
void customDisplayNameWithLongPattern(TestInfo testInfo) {
assertEquals("Details... :: repetition 1 of 1", testInfo.getDisplayName());
}
@RepeatedTest(value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}")
void repeatedTestInGerman() {
// ...
}
}
When using the ConsoleLauncher
with the unicode theme enabled, execution of RepeatedTestsDemo
results in the following output to the console.
├─ RepeatedTestsDemo ✔
│ ├─ repeatedTest() ✔
│ │ ├─ repetition 1 of 10 ✔
│ │ ├─ repetition 2 of 10 ✔
│ │ ├─ repetition 3 of 10 ✔
│ │ ├─ repetition 4 of 10 ✔
│ │ ├─ repetition 5 of 10 ✔
│ │ ├─ repetition 6 of 10 ✔
│ │ ├─ repetition 7 of 10 ✔
│ │ ├─ repetition 8 of 10 ✔
│ │ ├─ repetition 9 of 10 ✔
│ │ └─ repetition 10 of 10 ✔
│ ├─ repeatedTestWithRepetitionInfo(RepetitionInfo) ✔
│ │ ├─ repetition 1 of 5 ✔
│ │ ├─ repetition 2 of 5 ✔
│ │ ├─ repetition 3 of 5 ✔
│ │ ├─ repetition 4 of 5 ✔
│ │ └─ repetition 5 of 5 ✔
│ ├─ Repeat! ✔
│ │ └─ Repeat! 1/1 ✔
│ ├─ Details... ✔
│ │ └─ Details... :: repetition 1 of 1 ✔
│ └─ repeatedTestInGerman() ✔
│ ├─ Wiederholung 1 von 5 ✔
│ ├─ Wiederholung 2 von 5 ✔
│ ├─ Wiederholung 3 von 5 ✔
│ ├─ Wiederholung 4 von 5 ✔
│ └─ Wiederholung 5 von 5 ✔