Einführung in JUnitParams

Einführung in JUnitParams

1. Überblick

In diesem Artikel untersuchen wir die Bibliothek vonJUnitParamsund ihre Verwendung. Einfach ausgedrückt bietet diese Bibliothek eine einfache Parametrisierung der Testmethoden inJUnit Tests.

Es gibt Situationen, in denen sich zwischen mehreren Tests nur die Parameter ändern. JUnit selbst unterstützt die Parametrisierung, undJUnitParams verbessert diese Funktionalität erheblich.

2. Maven-Abhängigkeit

UmJUnitParams in unserem Projekt zu verwenden, müssen wir es zu unserenpom.xml hinzufügen:


    pl.pragmatists
    JUnitParams
    1.1.0

Die neueste Version der Bibliothek finden Sie unterhere.

3. Testszenario

Erstellen wir eine Klasse, in der zwei Ganzzahlen sicher addiert werden. Dies sollteInteger.MAX_VALUE zurückgeben, wenn es überläuft, undInteger.MIN_VALUE, wenn es unterläuft:

public class SafeAdditionUtil {

    public int safeAdd(int a, int b) {
        long result = ((long) a) + b;
        if (result > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        } else if (result < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        return (int) result;
    }
}

4. Aufbau einer einfachen Testmethode

Wir müssen die Methodenimplementierung für verschiedene Kombinationen von Eingabewerten testen, um sicherzustellen, dass die Implementierung für alle möglichen Szenarien gilt. JUnitParams bietet mehr als eine Möglichkeit, die parametrisierte Testerstellung zu erreichen.

Lassen Sie uns den grundlegenden Ansatz mit minimalem Codierungsaufwand verfolgen und sehen, wie es gemacht wird. Danach können wir sehen, welche anderen Möglichkeiten zur Implementierung der Testszenarien mit JUnitParams: sind

@RunWith(JUnitParamsRunner.class)
public class SafeAdditionUtilTest {

    private SafeAdditionUtil serviceUnderTest
      = new SafeAdditionUtil();

    @Test
    @Parameters({
      "1, 2, 3",
      "-10, 30, 20",
      "15, -5, 10",
      "-5, -10, -15" })
    public void whenWithAnnotationProvidedParams_thenSafeAdd(
      int a, int b, int expectedValue) {

        assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
    }

}

Nun wollen wir sehen, wie sich diese Testklasse von einer regulärenJUnit-Testklasse unterscheidet.

Das erste, was wir bemerken, ist, dassthere is adifferent test runner in der Klassenanmerkung -JUnitParamsRunner.

Wenn wir zur Testmethode übergehen, sehen wir, dass die Testmethode mit@Parameters Annotation mit einem Array von Eingabeparametern versehen ist. Es zeigt verschiedene Testszenarien an, die zum Testen unserer Servicemethode verwendet werden.

Wenn wir den Test mit Maven ausführen, sehen wir, dasswe are running four test cases and not a single one. Die Ausgabe würde ungefähr so ​​aussehen:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.example.junitparams.SafeAdditionUtilTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.068 sec
  - in com.example.junitparams.SafeAdditionUtilTest

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

5. Verschiedene Arten der Parametrisierung von Testmethoden

Das Bereitstellen von Testparametern direkt in der Annotation ist sicherlich nicht die am besten lesbare Methode, wenn wir viele mögliche Szenarien haben, die getestet werden müssen. JUnitParams bietet eine Reihe verschiedener Ansätze, mit denen wir die parametrisierten Tests erstellen können:

  • Direkt in der Annotation@Parameters (im obigen Beispiel verwendet)

  • Verwenden einer benannten Testmethode, die in der Anmerkung definiert ist

  • Verwenden einer Methode, die nach dem Namen der Testmethode zugeordnet ist

  • Eine benannte Testklasse, die in der Anmerkung definiert ist

  • Verwenden einer CSV-Datei

Lassen Sie uns die Ansätze einzeln erforschen.

5.1. Direkt in der Annotation@Parameters

Wir haben diesen Ansatz bereits in dem Beispiel verwendet, das wir ausprobiert haben. Was wir beachten müssen, ist, dass wir eine Reihe von Parameterzeichenfolgen bereitstellen sollten. Innerhalb der Parameterzeichenfolge wird jeder Parameter durch ein Komma getrennt.

Zum Beispiel würde das Array die Form von\{ “1, 2, 3”, “-10, 30, 20”} haben und ein Parametersatz wird als“1, 2, 3” dargestellt.

Die Einschränkung dieses Ansatzes besteht darin, dass wir nur Primitive undStrings als Testparameter angeben können. Es ist nicht möglich, Objekte auch als Testmethodenparameter zu übergeben.

5.2. Parametermethode

Wir können die Testmethodenparameter mit einer anderen Methode innerhalb der Klasse bereitstellen. Sehen wir uns zuerst ein Beispiel an:

@Test
@Parameters(method = "parametersToTestAdd")
public void whenWithNamedMethod_thenSafeAdd(
  int a, int b, int expectedValue) {

    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

private Object[] parametersToTestAdd() {
    return new Object[] {
        new Object[] { 1, 2, 3 },
        new Object[] { -10, 30, 20 },
        new Object[] { Integer.MAX_VALUE, 2, Integer.MAX_VALUE },
        new Object[] { Integer.MIN_VALUE, -8, Integer.MIN_VALUE }
    };
}

Die Testmethode ist in Bezug auf die MethodeparametersToAdd(), mit Anmerkungen versehen und ruft die Parameter ab, indem die referenzierte Methode ausgeführt wird.

Die Angabe der Anbietermethode sollte daher ein Array vonObjects zurückgeben. Wenn eine Methode mit dem angegebenen Namen nicht verfügbar ist, schlägt der Testfall mit dem Fehler fehl:

java.lang.RuntimeException: Could not find method: bogusMethodName so no params were used.

5.3. Methode nach Name der Testmethode zugeordnet

Wenn wir in der Annotation@Parametersnichts angeben, versuchtJUnitParams, eine Testdatenprovider-Methode basierend auf dem Namen der Testmethode zu laden. Der Methodenname wird als“parametersFor”+ <test method name>: konstruiert

@Test
@Parameters
public void whenWithnoParam_thenLoadByNameSafeAdd(
  int a, int b, int expectedValue) {

    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

private Object[] parametersForWhenWithnoParam_thenLoadByNameSafe() {
    return new Object[] {
        new Object[] { 1, 2, 3 },
        new Object[] { -10, 30, 20 },
        new Object[] { Integer.MAX_VALUE, 2, Integer.MAX_VALUE },
        new Object[] { Integer.MIN_VALUE, -8, Integer.MIN_VALUE }
    };
}

Im obigen Beispiel lautet der Name der TestmethodewhenWithnoParam_shouldLoadByNameAbdSafeAdd().

Daher sucht die Testmethode bei der Ausführung nach einer Datenprovidermethode mit dem NamenparametersForWhenWithnoParam_shouldLoadByNameAbdSafeAdd().

Da diese Methode vorhanden ist, werden Daten daraus geladen und der Test ausgeführt. If there is no such method matching the required name, the test fails wie im obigen Beispiel.

5.4. Benannte Testklasse, die in der Anmerkung definiert ist

Ähnlich wie wir in einem vorherigen Beispiel auf eine Datenprovidermethode verwiesen haben, können wir auf eine separate Klasse verweisen, um die Daten für unseren Test bereitzustellen:

@Test
@Parameters(source = TestDataProvider.class)
public void whenWithNamedClass_thenSafeAdd(
  int a, int b, int expectedValue) {

    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
public class TestDataProvider {

    public static Object[] provideBasicData() {
        return new Object[] {
            new Object[] { 1, 2, 3 },
            new Object[] { -10, 30, 20 },
            new Object[] { 15, -5, 10 },
            new Object[] { -5, -10, -15 }
        };
    }

    public static Object[] provideEdgeCaseData() {
        return new Object[] {
            new Object[] {
              Integer.MAX_VALUE, 2, Integer.MAX_VALUE },
            new Object[] {
              Integer.MIN_VALUE, -2, Integer.MIN_VALUE },
        };
    }
}

Wir können eine beliebige Anzahl von Testdatenanbietern in einer Klasse haben, da der Methodenname mit "supply" beginnt. In diesem Fall wählt der Executor diese Methoden aus und gibt die Daten zurück.

Wenn keine Klassenmethoden diese Anforderung erfüllen, werden diese Methoden ignoriert, obwohl diese Methoden ein Array vonObjects zurückgeben.

5.5. Verwenden einer CSV-Datei

Wir können eine externe CSV-Datei verwenden, um die Testdaten zu laden. Dies ist hilfreich, wenn die Anzahl der möglichen Testfälle sehr hoch ist oder wenn Testfälle häufig geändert werden. Die Änderungen können ohne Auswirkung auf den Testcode vorgenommen werden.

Nehmen wir an, wir haben eine CSV-Datei mit Testparametern alsJunitParamsTestParameters.csv:

1,2,3
-10, 30, 20
15, -5, 10
-5, -10, -15

Schauen wir uns nun an, wiethis file can be used to load test parametersin der Testmethode enthalten ist:

@Test
@FileParameters("src/test/resources/JunitParamsTestParameters.csv")
public void whenWithCsvFile_thenSafeAdd(
  int a, int b, int expectedValue) {

    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

Eine Einschränkung dieses Ansatzes besteht darin, dass es nicht möglich ist, komplexe Objekte zu übergeben. Es sind nur Grundelemente undStrings gültig.

6. Fazit

In diesem Tutorial haben wir uns angesehen, wie wir die Funktionen vonJUnitParams auf den Punkt bringen können.

Wir haben auch verschiedene Ansätze behandelt, mit denen die Bibliothek Testparameter für unsere Testmethoden bereitstellt - weit über das hinaus, was JUnit selbst kann.

Wie immer kann der Quellcodeover on GitHub gefunden werden.