[JAVA] Einführung in den Parametrisierungstest in JUnit

Überblick

Unabhängig von JUnit lautet der Geräte-Setup-Code im Testcode Es ist in der Regel lang und verringert die Lesbarkeit.

In diesem Artikel konzentrieren wir uns auf "Eingabewert" und "Erwartungswert" aus den Elementen der Testvorrichtung. Wir werden die Methode zur klaren Beschreibung dieser Präparate durch Parametrisierung zusammenfassen.

Parametrierung von Eingabe- und Erwartungswerten

Die folgenden vier Schritte sind für den Parametrisierungstest von JUnit erforderlich.

  1. Geben Sie der Testklasse Theories Test Runner
  2. Fügen Sie dem Testfall die Annotation Theory hinzu und geben Sie die zu empfangenden Parameter an. (Wenn Sie Schritt 4 nicht ausführen, werden alle Kombinationen der angegebenen Parameter ausgeführt.)
  3. Bereiten Sie die Parameter vor
  4. Definieren Sie eine Kombination von Parametern, die nicht ausgeführt werden

1. 1. Theorien Testläufer

Wenn Sie einen parametrisierten Test durchführen möchten, fügen Sie die Annotation RunWith in die Testklasse ein Geben Sie die Klasse org.junit.experimental.theories.Theories an. Der Teories-Testläufer kann mit dem geschlossenen Testläufer verwendet werden.

@RunWith(Enclosed.class)
public class ParameterizedTest {

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen{
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zeichenfolgen{
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen und Zeichenfolgen{
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen und Zahlen{
    }
}

2. Theorie Annotation

Für Testmethoden, die Parameter verwenden möchten, Fügen Sie anstelle der Testanmerkung eine Theorie-Annotation hinzu.

Testmethoden mit Theory-Annotationen können beliebige Argumente deklarieren. Mitglieder mit den unten beschriebenen Anmerkungen zu DataPoint und DataPoints Setzen Sie das Argument als Parameter.

@RunWith(Enclosed.class)
public class ParameterizedTest {

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen{
        @Theory
        public void testCase(int num) throws Exception {
        }
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zeichenfolgen{
        @Theory
        public void testCase(String str) throws Exception {
        }
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen und Zeichenfolgen{
        @Theory
        public void testCase(int num, String str) throws Exception {
        }
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen und Zahlen{
        @Theory
        public void testCase(int num1, int num2) throws Exception {
        }
    }
}

3. 3. Parametervorbereitung

DataPoint-Annotation

Im parametrisierten Test mit Theories Test Runner Definieren Sie Parameter mithilfe der DataPoint-Annotation. Parameter werden in statischen und öffentlichen Feldern oder Methoden definiert.

Das Argument der Methode mit Theory Annotation ist Von den Werten mit der DataPoint-Annotation die Parameter, die dem Typ entsprechen Alle Kombinationen werden als Argumente übergeben.

@RunWith(Enclosed.class)
public class ParameterizedTest {

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen{
        @DataPoint
        public static int INT_PARAM_1 = 3;
        @DataPoint
        public static int INT_PARAM_2 = 4;
        
        @Theory
        public void testCase(int num) throws Exception {
        	System.out.println("Eingegebener Wert:" + num);
        }
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zeichenfolgen{
        @DataPoint
        public static String STR_PARAM_1 = "Hello";
        @DataPoint
        public static String STR_PARAM_2 = "World";
        
        @Theory
        public void testCase(String str) throws Exception {
        	System.out.println("Eingegebener Wert:" + str);
        }
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen und Zeichenfolgen{
    	@DataPoint
        public static int INT_PARAM_1 = 3;
        @DataPoint
        public static int INT_PARAM_2 = 4;
        @DataPoint
        public static String STR_PARAM_1 = "Hello";
        @DataPoint
        public static String STR_PARAM_2 = "World";
        
        @Theory
        public void testCase(int num, String str) throws Exception {
        	System.out.println("Eingegebener Wert:" + num + "、" + str);
        }
    }

    @RunWith(Theories.class)
öffentliche statische Klasse Für Zahlen und Zahlen{
    	@DataPoint
        public static int INT_PARAM_1 = 3;
        @DataPoint
        public static int INT_PARAM_2 = 4;
        
        @Theory
        public void testCase(int num1, int num2) throws Exception {
        	System.out.println("Eingegebener Wert:" + num1 + "、" + num2);
        }
    }
}

Wenn ParameterizedTest ausgeführt wird, werden die folgenden Inhalte an die Konsole ausgegeben.

~ Bei numerischem Wert ~
Eingabewert: 3
Eingabewert: 4

~ Bei Zeichenkette ~
Eingabewert: Hallo
Eingabewert: Welt

~ Für Zahlen und Zeichenfolgen ~
Eingabewert: 3, Hallo
Eingabewert: 3, Welt
Eingabewert: 4, Hallo
Eingabewert: 4, Welt

~ Bei numerischen Werten und numerischen Werten ~
Eingabewert: 3, 3
Eingabewerte: 3, 4
Eingabewerte: 4, 3
Eingabewerte: 4, 4

Verwendung von Vorrichtungsobjekten

Wenn mehr Argumente an die Theory-Methode übergeben werden Durch Deklarieren eines statischen DTO in der Testklasse können die Argumente zu einem kombiniert werden. Das DTO, das das Argument enthält, wird als Fixture-Objekt bezeichnet.

@RunWith(Theories.class)
public class ParameterizedTest {
    @DataPoint
    public static Fixture INT_PARAM_1 = new Fixture(1, 2, 3);
    @DataPoint
    public static Fixture INT_PARAM_2 = new Fixture(0, 2, 2);

    @Theory
    public void testCase(Fixture params) throws Exception {
        assertThat(params.x + params.y, is(params.expected));
    }

    static class Fixture {
        int x;
        int y;
        int expected;

        Fixture(int x, int y, int expected) {
            this.x = x;
            this.y = y;
            this.expected = expected;
        }
    }
}

DataPoints-Annotation

Die DataPoint-Annotation konnte nur einen Parameter definieren: Mit der DataPoints-Annotation können mehrere Parameter an einer Stelle definiert werden.

@RunWith(Theories.class)
public class ParameterizedTest {
    @DataPoints
    public static Fixture[] INT_PARAMS = {
        new Fixture(1, 2, 3),
        new Fixture(0, 2, 2),
    };
    /*Definition mit DataPoint-Annotation
    @DataPoint
    public static Fixture INT_PARAM_1 = new Fixture(1, 2, 3);
    @DataPoint
    public static Fixture INT_PARAM_2 = new Fixture(0, 2, 2);
    */

    @Theory
    public void testCase(Fixture params) throws Exception {
        assertThat(params.x + params.y, is(params.expected));
    }

    static class Fixture {
        int x;
        int y;
        int expected;

        Fixture(int x, int y, int expected) {
            this.x = x;
            this.y = y;
            this.expected = expected;
        }
    }
}

Externe Ressource (YAML-Datei)

params.yaml


!!seq [
  !!test.ParameterizedTest$Fixture
  { x: 1, y: 2, expected: 3 },
  !!test.ParameterizedTest$Fixture
  { x: 0, y: 2, expected: 2 },
]
@RunWith(Theories.class)
public class ParameterizedTest {
    @DataPoints
    public static Fixture[] INT_PARAMS = {
        InputStream in = ParameterizedTest.class
                            .getResourceAsStream("params.yaml");
        return ((List<Fixture>) new Yaml().load(in)).toArray(new Fixture[0]);
    };
    /*Definition mit DataPoint-Annotation
    @DataPoint
    public static Fixture INT_PARAM_1 = new Fixture(1, 2, 3);
    @DataPoint
    public static Fixture INT_PARAM_2 = new Fixture(0, 2, 2);
    */

    @Theory
    public void testCase(Fixture params) throws Exception {
        assertThat(params.x + params.y, is(params.expected));
    }

    static class Fixture {
        int x;
        int y;
        int expected;

        Fixture(int x, int y, int expected) {
            this.x = x;
            this.y = y;
            this.expected = expected;
        }
    }
}

Vier. Klasse annehmen

Wenn Sie nur die Parameter angeben, werden alle Testkombinationen ausgeführt. In einem solchen Fall stimmen einige Kombinationen möglicherweise nicht mit den erwarteten Werten des Tests überein.

Mit dem obigen Test wurde beispielsweise überprüft, ob der Mehrwert dem erwarteten Wert entspricht. Wenn dies ein Test ist, um zu überprüfen, ob der Mehrwert gerade ist Im Fall von x = 1 und y = 2 ist der Eingabewert nicht wie erwartet.

Verwenden Sie in diesen Fällen die Assume-Klasse Es können nur die vom Testfall angenommenen Eingabewerte übergeben werden.

Die von der Assume-Klasse bereitgestellten Methoden umfassen asumeTrue und acceptThat. Implementieren Sie jedes wie folgt.

assumeTrue(Bedingter Ausdruck);
assumeThat(Eingegebener Wert,Matcher-Methode);

Was die Bewegung betrifft, wenn das Urteil in der Methode in beiden Fällen falsch ist, Mit anderen Worten, wenn der Eingabewert nicht wie erwartet ist, wird eine AssumptionViolatedException generiert. Es wird keine weitere Verarbeitung durchgeführt. (Dient als Rückgabeklausel im Testcode) Diese Ausnahme wird im Testläufer speziell behandelt, und selbst wenn die Ausnahme abgefangen wird, ist das Testergebnis erfolgreich.

@RunWith(Theories.class)
public class ParameterizedTest {
    @DataPoints
    public static Fixture[] INT_PARAMS = {
        new Fixture(1, 2, 3),
        new Fixture(0, 2, 2),
    };

    @Theory
    public void testCase(Fixture params) throws Exception {
        //Der Eingabewert wird nach der Addition als gerader Wert angenommen.
        //Unerwarteter Eingabewert(assumeTrue(false)Was wird)Im Fall von wird die nachfolgende Verarbeitung nicht durchgeführt
        assumeTrue((params.x + params.y) % 2 == 0);
        // x + y =Stellen Sie sicher, dass es gerade ist
        assertThat((params.x + params.y) % 2 == 0 , is(true));
    }

    static class Fixture {
        int x;
        int y;
        int expected;

        Fixture(int x, int y, int expected) {
            this.x = x;
            this.y = y;
            this.expected = expected;
        }
    }
}

Parametrisierte Testprobleme

Datenabdeckung

Die Vollständigkeit, die ein Index für die Testqualität ist, hängt von der Parameterspezifikation und der Annahmeklasse ab. Da es der Implementierer ist, der die Filterung durchführt, nur weil alle Kombinationen getestet werden Es ist kein Testfall, der Anforderungen und Spezifikationen abdeckt. In Bezug auf die Gültigkeit und Vollständigkeit der Testdaten unter dem Prüfer, der mit der Testtechnik vertraut ist, Es ist notwendig, Maßnahmen wie die Überprüfung zu ergreifen.

Mangel an Informationen über Parameter

Beim Testen mit Theories Test Runner wird der Bericht angezeigt, wenn der Test fehlschlägt Die Information "Welcher Parameter ist fehlgeschlagen?" Fehlt. Daher ist es beim parametrisierten Test erforderlich, Maßnahmen zu ergreifen, um die einfache Untersuchung zu berücksichtigen, wenn der Test fehlschlägt.

/*Beispiel) Verwenden Sie die Methode assertThat, um den Eingabewert zum Zeitpunkt des Fehlers an die Nachricht auszugeben*/
@Theory
public void testCase(Fixture params) throws Exception {
    assumeTrue((params.x + params.y) % 2 == 0);
    String failMsg = "Fail when x = " + params.x + ", y = " + params.y;
    assertThat(failMsg, (params.x + params.y) % 2 == 0 , is(true));
}

Verweise

Dieser Artikel wurde unter Bezugnahme auf die folgenden Informationen verfasst.

Recommended Posts

Einführung in den Parametrisierungstest in JUnit
Erste Schritte mit DBUnit
Erste Schritte mit Ruby
Erste Schritte mit Swift
Erste Schritte mit Doma-Transaktionen
Erste Schritte mit der Verarbeitung von Doma-Annotationen
Erste Schritte mit Java Collection
Erste Schritte mit JSP & Servlet
Erste Schritte mit Java Basics
Erste Schritte mit Spring Boot
Erste Schritte mit Ruby-Modulen
Testen der Sende- und Empfangslogik von Anforderungen mit MockWebServer in JUnit
Erste Schritte mit Java_Kapitel 5_Praktische Übungen 5_4
[Google Cloud] Erste Schritte mit Docker
Erste Schritte mit Docker mit VS-Code
Erste Schritte mit dem Doma-Criteria API Cheet Sheet
Erste Schritte mit Ruby für Java-Ingenieure
Einführung in Java ab 0 Teil 1
Erste Schritte mit Ratpack (4) -Routing & Static Content
Beginnen Sie mit der Funktionsweise von JVM GC
Erste Schritte mit dem Language Server Protocol mit LSP4J
Erste Schritte mit dem Erstellen von Ressourcenpaketen mit ListResoueceBundle
Links & Memos für den Einstieg in Java (für mich)
Erste Schritte mit der Doma-Projektion mit der Criteira-API
Erste Schritte mit Java 1 Ähnliche Dinge zusammenstellen
Erste Schritte mit Kotlin zum Senden an Java-Entwickler
Erste Schritte mit Doma-Using Joins mit der Criteira-API
Testen mit com.google.testing.compile
Refactoring in JUnit
Erste Schritte mit Doma-Einführung in die Kriterien-API
Ich habe versucht, mit Gradle auf Heroku zu beginnen
Erste Schritte mit Java-Programmen mit Visual Studio Code
[JUnit 5] Schreiben Sie einen Validierungstest mit Spring Boot! [Parametrisierungstest]
Erste Schritte mit älteren Java-Ingenieuren (Stream + Lambda)
Machen Sie einen Unit-Test mit Junit.
Beginnen Sie mit Gradle
Erste Schritte mit Java und Erstellen eines Ascii Doc-Editors mit JavaFX
Erste Schritte mit Doma-Dynamic Erstellen von WHERE-Klauseln mit der Kriterien-API
Erste Schritte mit Reactive Streams und der JDK 9 Flow API
Beachten Sie beim Testen privater Methoden in JUnit
Erste Schritte mit der Git Hub Container Registry anstelle von Docker Hub
Beispielcode für das grundlegende Verspotten und Testen mit Mockito 3 + JUnit 5