How do I write repeated tests in JUnit?

In JUnit 5, repeated tests are written using the @RepeatedTest annotation.

A repeated test runs the same test method multiple times without requiring different input values.

Basic Example

import org.junit.jupiter.api.RepeatedTest;

import static org.junit.jupiter.api.Assertions.assertTrue;

class RandomNumberTest {

    @RepeatedTest(5)
    void randomNumberShouldBeLessThanTen() {
        int number = (int) (Math.random() * 10);

        assertTrue(number >= 0 && number < 10);
    }
}

This test runs 5 times.

Difference Between @Test and @RepeatedTest

Instead of writing:

import org.junit.jupiter.api.Test;

class ExampleTest {

    @Test
    void shouldRunOnce() {
        // test logic
    }
}

You write:

import org.junit.jupiter.api.RepeatedTest;

class ExampleTest {

    @RepeatedTest(3)
    void shouldRunThreeTimes() {
        // test logic
    }
}

Access the Current Repetition

JUnit can inject a RepetitionInfo parameter into a repeated test. This lets you know which repetition is currently running.

import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;

import static org.junit.jupiter.api.Assertions.assertTrue;

class RetryExampleTest {

    @RepeatedTest(5)
    void repeatedTestWithInfo(RepetitionInfo repetitionInfo) {
        int current = repetitionInfo.getCurrentRepetition();
        int total = repetitionInfo.getTotalRepetitions();

        System.out.println("Running repetition " + current + " of " + total);

        assertTrue(current >= 1);
        assertTrue(current <= total);
    }
}

Example output:

Running repetition 1 of 5
Running repetition 2 of 5
Running repetition 3 of 5
Running repetition 4 of 5
Running repetition 5 of 5

Customize the Display Name

You can customize the name shown for each repeated test invocation.

import org.junit.jupiter.api.RepeatedTest;

class LoginTest {

    @RepeatedTest(value = 3, name = "Login attempt {currentRepetition} of {totalRepetitions}")
    void loginShouldSucceedRepeatedly() {
        // test login logic
    }
}

This may display as:

Login attempt 1 of 3
Login attempt 2 of 3
Login attempt 3 of 3

Common placeholders are:

{displayName}
{currentRepetition}
{totalRepetitions}

JUnit also provides predefined formats:

@RepeatedTest(value = 3, name = RepeatedTest.SHORT_DISPLAY_NAME)

or:

@RepeatedTest(value = 3, name = RepeatedTest.LONG_DISPLAY_NAME)

Example with @BeforeEach

Lifecycle methods such as @BeforeEach run before each repetition.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;

import static org.junit.jupiter.api.Assertions.assertEquals;

class CounterTest {

    private int counter;

    @BeforeEach
    void setUp() {
        counter = 0;
    }

    @RepeatedTest(3)
    void counterStartsAtZeroEachTime() {
        assertEquals(0, counter);

        counter++;
    }
}

Because @BeforeEach runs before every repetition, the counter starts at 0 each time.

When to Use Repeated Tests

Use @RepeatedTest when you want to run the same test multiple times, for example:

  • testing code that uses random values
  • checking for flaky behavior
  • verifying repeated operations
  • testing concurrency-related code
  • making sure state is reset between runs

@RepeatedTest vs Parameterized Tests

Use @RepeatedTest when the test logic is the same and the input does not change.

Use parameterized tests when you want to run the same test with different inputs.

@RepeatedTest(5)
void sameTestRepeatedSeveralTimes() {
    // same input or generated input each time
}
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void sameTestWithDifferentValues(int value) {
    // runs once for each value
}

Maven Dependency

Make sure JUnit Jupiter is available in your project:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.13.4</version>
    <scope>test</scope>
</dependency>

Gradle Dependency

testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'

test {
    useJUnitPlatform()
}

Summary

Use @RepeatedTest to run the same test multiple times:

import org.junit.jupiter.api.RepeatedTest;

class ExampleTest {

    @RepeatedTest(5)
    void shouldRunFiveTimes() {
        // test logic
    }
}

A repeated test is useful when you need the same test executed more than once, while a parameterized test is better when each run needs different input data.