@RepeatedTest w JUnit 5 czyli powtarzanie testu

Wstęp

Biblioteka JUnit 5 wprowadziła możliwość powtarzania testów wybraną liczbę razy. Wystarczy, że zastąpimy adnotację @Test na @RepeatedTest podając jako argument liczbę powtórzeń.

import org.junit.jupiter.api.RepeatedTest;

public class RepetitionTest {

    @RepeatedTest(10)
    void testSomething() {

    }
}

W ramach wyniku zobaczyć można każde uruchomienie metody testowej:

junit-5-repetition.png

Zmiana wyświetlanej nazwy

Istnieje możliwość zmiany wyświetlanej nazwy testu w wynikach. Możemy wykorzystać jedną z wartości:

  • RepeatedTest.SHORT_DISPLAY_NAME - jest to wartość domyślna widoczna powyżej
  • RepeatedTest.LONG_DISPLAY_NAME - wartość tej stałej to: {displayName} :: repetition {currentRepetition} of {totalRepetitions}
    @RepeatedTest(value = 10, name = LONG_DISPLAY_NAME)
    void testSomething() {

    }

Wynik jest następujący:

junit-5-repetition-long-name.png

Możemy również samemu zdefiniować wyświetlaną nazwę:

    @RepeatedTest(value = 10, name = "powtórzenie {currentRepetition} z {totalRepetitions}")
    void testSomething() {

    }

Uzyskując taki wynik:

junit-5-repetition-custom-name.png

Informacja o powtórzeniu

Istnieje możliwość uzyskania informacji o tym które powtórzenie jest aktualnie wykonywane. W tym celu należy skorzystać z mechanizmu wstrzykiwania i jako argument metody testowej podać RepetitionInfo.

    @RepeatedTest(10)
    void testSomething(RepetitionInfo repetitionInfo) {
        System.out.println("Wykonuję powtórzenie " + repetitionInfo.getCurrentRepetition());
    }

Kurs JUnit i Testowanie jednostkowe

W konsoli wyświetli się wtedy:

Wykonuję powtórzenie 1
Wykonuję powtórzenie 2
Wykonuję powtórzenie 3
Wykonuję powtórzenie 4
Wykonuję powtórzenie 5
Wykonuję powtórzenie 6
Wykonuję powtórzenie 7
Wykonuję powtórzenie 8
Wykonuję powtórzenie 9
Wykonuję powtórzenie 10

Integracja z @BeforeEach i @AfterEach

Metody oznaczone @BeforeEach oraz @AfterEach wykonają się przed i po każdym wykonaniu testu. Tam również można wstrzyknąć RepetitionInfo.

import org.junit.jupiter.api.*;

public class RepetitionTest {

    private long timestamp;

    @BeforeEach
    void before(TestInfo testInfo, RepetitionInfo repetitionInfo) {
        System.out.println("Uruchamiam test " + testInfo.getDisplayName());
        timestamp = System.currentTimeMillis();
    }

    @RepeatedTest(value = 5, name = "MojTest")
    void testSomething(RepetitionInfo repetitionInfo) throws InterruptedException {
        System.out.println("Wykonuję powtórzenie " + repetitionInfo.getCurrentRepetition());
        Thread.sleep(100);
    }

    @AfterEach
    void after(TestInfo testInfo, RepetitionInfo repetitionInfo) {
        System.out.println("Wykonanie testu " + testInfo.getDisplayName() + " "
                + repetitionInfo.getCurrentRepetition() + "/" + repetitionInfo.getTotalRepetitions()
                + " trwało: " + (System.currentTimeMillis() - timestamp) + "ms");
    }
}

Wynik:

Uruchamiam test MojTest
Wykonuję powtórzenie 1
Wykonanie testu MojTest 1/5 trwało: 111ms

Uruchamiam test MojTest
Wykonuję powtórzenie 2
Wykonanie testu MojTest 2/5 trwało: 102ms

Uruchamiam test MojTest
Wykonuję powtórzenie 3
Wykonanie testu MojTest 3/5 trwało: 102ms

Uruchamiam test MojTest
Wykonuję powtórzenie 4
Wykonanie testu MojTest 4/5 trwało: 104ms

Uruchamiam test MojTest
Wykonuję powtórzenie 5
Wykonanie testu MojTest 5/5 trwało: 104ms

Zastosowanie @RepeatedTest

Szczerze mówiąc, to ciężko wymyślić zastosowanie tej funkcjonalności w przypadku typowych testów jednostkowych, gdzie testujemy w izolacji i bezstanowo. Przydać natomiast może się w przypadku bardziej zaawansowanych testów funkcjonalnych lub integracyjnych.

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.