Niedawno dopisałem do Tumblera możliwość definiowania scenariuszy parametryzowanych. Chodzi o to, żeby móc zdefiniować parę zestawów parametrów scenariusza i mieć ten sam jeden scenariusz wykonany dla wszystkich zestawów, weryfikując w ten sposób jego poprawność dla różnych danych. Ale jako, że nie wszyscy chcą używać Tumblera (i nie zawsze jest sens), przepisałem tę funkcjonalność do czystego JUnit’a. Po co? Głównie dlatego, że testy parametryzowane w JUnit to porażka. Z runnerem Parameterized Testy są wg. mnie mniej czytelne, tworzy się dużo klas, generalnie kiszka. Na dodatek do Parameterized są też teorie, które miały rozwiązać parę problemów, ale chyba nikt ich nie używa.
Ostatnio jednak mieliśmy w projekcie sytuację, w której testy parametryzowane byłyby wygodne… gdyby były wygodne. Więc wyciągnąłem ten kawałek Tumbler’a na zewnątrz i tak powstał JUnitParams. Teraz testy parametryzowane w JUnit są dużo przyjemniejsze.

Jak to działa?
1. Trzeba zdefiniować runner (JUnitParamsRunner) –  bo JUnit nie umie wykonać tego samego testu parę razy, a przecież o to nam chodzi.
2. Stworzyć metodę testową z parametrami metody testowej oraz zadnotować ją za pomocą @Parameters podając parametry bezpośrednio w adnotacji, lub podając klasę dostarczającą te wartości z zewnątrz. Jeśli chcemy podać parametry bezpośrednio, to podajemy je jako tablicę String’ów, której każdy element jest jednym zestawem parametrów:
@Parameters({“1, Jaś, true”, “2, Andżelika, false” })
Tak podane parametry są następnie parsowane i rzutowane na odpowiednie podstawowe typy javowe.
Jeśli zaś zestawów parametrów ma być więcej, lub chcemy je pobrać dynamicznie np. z pliku bądź bazy, możemy podać klasę dostarczającą wartości parametrów:
@Parameters(source=NamesParamsProvider.class)
Co do tej klasy nie ma żadnych wymagań poza posiadaniem przynajmniej jednej publicznej statycznej bezparametrowej metody zaczynającej się od provide. Wszystkie takie metody są uruchamiane, ich wyniki zbierane i dostarczane do metody testowej.
Można też przekazywać parametry bez zewnętrznej klasy – podając metodę testu zwracającą dane w adnotacji:
@Parameters(method=”samplePeople”)
3. Już. Żadnych konstruktorów, pól w klasie testowej, czy innych zbędnych dodatków.

Przykładowy test z parametrami wygląda np. tak:

@RunWith(JUnitParamsRunner.class)
public class PersonTest {

  @Test
  @Parameters(method = "adultValues")
  public void isAdult(int age, boolean valid) {
    assertThat(new Person(age).isAdult(), is(valid));
  }

  private Object[] adultValues() {
    return $(
      $(17, false),
      $(22, true)
    );
  }
}

Więcej przykładów na stronie projektu.