JUnit 5 – Testy powtarzalne

Jedną z cech testów jednostkowych jest ich powtarzalność. Najlepiej, jeżeli powtórzenie jest wykonywane automatycznie. Jednak nie o tym dziś będziemy mówić. Czasami pisząc testy, musimy uwzględnić, że nasz kod uruchamiany jest w środowisku wielowątkowym. Nie ma w tym nic nadzwyczajnego. Podobnie jest w przypadku, gdy tworzymy testy, których zadaniem jest jakiegoś kodu w wielu kopiach jednocześnie. Dla mnie wzorcową implementacją tego zachowania jest TestNG:

Listing 1. Testy powtarzalne w TestNG

@Test
public class FizzBuzzTestNGRepeatedTest {

	private FizzBuzz sut;

	@BeforeTest
	public void setup() {
		sut = new FizzBuzz();
	}

	@Test(invocationCount = 100, threadPoolSize = 4)
	public void shouldReturnFizzBuzzIfDiv3And5() throws Exception {
		assertEquals("FizzBuzz", sut.fizzBuzz(15));
	}

	@Test(invocationCount = 100, threadPoolSize = 4)
	public void shouldReturnBuzzIfDiv5() throws Exception {
		assertEquals("Buzz", sut.fizzBuzz(5));
	}

	@Test(invocationCount = 100, threadPoolSize = 4)
	public void shouldReturnFizzIfDiv3() throws Exception {
		assertEquals("Fizz", sut.fizzBuzz(3));
	}

	@Test(invocationCount = 100, threadPoolSize = 4)
	public void shouldReturnVal() throws Exception {
		assertEquals("2", sut.fizzBuzz(2));
	}

}

Mamy tu dość dużą elastyczność w konfiguracji testów. Po pierwsze za pomocą parametru invocationCount, możemy określić, ile testów ma zostać wykonanych. Po drugie parametr threadPoolSize pozwala nam na skonfigurowanie liczby wątków użytych do uruchomienia testów.

W przypadku JUnit 5 wygląda to trochę inaczej. Po pierwsze wprowadzono adnotację @RepeatedTest, która pozwala na określenie liczby powtórzeń. Adnotacja ta zachowuje się jak specjalizowana @Test.

Listing 2. Testy powtarzalne w JUnit 5

public class FizzBuzzJUnit5RepeatedTest {

	private FizzBuzz sut;

	@BeforeEach
	public void setup() {
		sut = new FizzBuzz();
	}

	@RepeatedTest(value = 100, name = "Repetition {currentRepetition} of {totalRepetition}")
	public void shouldReturnFizzBuzzIfDiv3And5() throws Exception {
		assertEquals("FizzBuzz", sut.fizzBuzz(15));
	}

	@RepeatedTest(value = 100, name = "Repetition {currentRepetition} of {totalRepetition}")
	public void shouldReturnBuzzIfDiv5() throws Exception {
		assertEquals("Buzz", sut.fizzBuzz(5));
	}

	@RepeatedTest(value = 100, name = "Repetition {currentRepetition} of {totalRepetition}")
	public void shouldReturnFizzIfDiv3() throws Exception {
		assertEquals("Fizz", sut.fizzBuzz(3));
	}

	@RepeatedTest(value = 100, name = "Repetition {currentRepetition} of {totalRepetition}")
	public void shouldReturnVal() throws Exception {
		assertEquals("2", sut.fizzBuzz(2));
	}
}

Po drugie, adnotacja ta ma parametr name, który pozwala na dodanie nazwy specyficznej dla uruchomienia. W nazwie tej możemy wykorzystać trzy flagi:

  • {currentRepetition} – w której jest numer aktualnego przebiegu,
  • {totalRepetition} – w której mamy ilość wszystkich przebiegów,
  • {displayName} – która zawiera nazwę testu zdefiniowaną w @DisplayName.

Możemy też jako wartość parametru podać jedną ze stałych zdefiniowanych w samej adnotacji:

  • SHORT_DISPLAY_NAME – która jest równoważna „repetition {currentRepetition} of {totalRepetition}”,
  • LONG_DISPLAY_NAME – która jest równoważna „{displayName} :: repetition {currentRepetition} of {totalRepetition}”.

Problem polega jednak na tym, że nie możemy skonfigurować liczby wątków, które zostaną wykorzystane do uruchomienia testu. Nie pozostaje nic innego jak użycie specyficznego silnika, którego oczywiście jeszcze nie ma.

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax