[JAVA] [JUnit 5] Schreiben Sie einen Validierungstest mit Spring Boot! [Parametrisierungstest]

Einführung

Hallo! Dies ist die fünfte Serie, die von Grund auf mit Java spielt. Dieses Mal werden wir eine Testklasse für die Validierung erstellen, die wir das letzte Mal durchgeführt haben.

Wenn Sie es verderben, ist es die Art von Qiita-Post, die zuerst ein Fehlerbeispiel hat. Wenn Sie schnell ein Beispiel für den Parametrisierungstest sehen möchten, springen Sie bitte zu ◎ Gutes Beispiel

Klicken Sie hier für Artikel bis zum letzten Mal ↓

  1. Erstellen einer STS-Umgebung auf einem Mac
  2. Hallo Welt mit Spring Boot
  3. Echoanwendung mit Spring Boot erstellen
  4. Formularüberprüfung mit Spring Boot erstellen

Synopse bis zum letzten Mal

Die aktuellen Validierungsanforderungen lauten wie folgt. Der Formularklasse werden Anmerkungen hinzugefügt, um die folgenden Zeichentypen und die Anzahl der Zeichen zu überprüfen.

画面収録 2020-07-21 23.39.15.mov.gif

Nutzungsumgebung und Version

[△ Schlechtes Beispiel (1)] Kopieren Sie einen anderen als den Einstellungsteil der zu testenden und redundanten Variablen und fügen Sie ihn ein

Da wir mit der Formularklasse validieren, erstellen wir eine Testklasse für die Formularklasse. Es gibt vier Fälle, die ich dieses Mal testen möchte.

  1. Normales System (kein Fehler)
  2. Anormales System (falsche Anzahl von Zeichen)
  3. Anormales System (Zeichentyp ungültig)
  4. Anormales System (unzulässige Anzahl von Zeichen und falscher Zeichentyp)

Selbst im normalen System sind alphanumerische Zeichen mit halber Breite zulässig. Wenn Sie also einen strengeren Test durchführen möchten, möchten Sie ein Datenmuster, das nur aus Zahlen, nur alphabetischen Zeichen und alphanumerischen Zeichen besteht. Ich möchte auch Datenmuster wie Hiragana, Katakana, Kanji, alphanumerische Zeichen in voller Breite, Symbole usw. für abnormale Zeichentypfehler erstellen ... [^ 1]

Der folgende Code wurde in Eile mit 3 Mustern des normalen Systems, 2 Mustern mit falscher Anzahl von Zeichen und 2 Mustern mit falschem Zeichentyp erstellt. Der JUnit-Test besteht immer noch, aber die Testausführung und die Ergebnisüberprüfung sind sehr redundant, da derselbe Code wiederholt wird (Kesselplattencode) ... Darüber hinaus sind abnormale Kanji und Hiragana, gemischte Zeichentypmuster und abnormale Typen, bei denen sowohl die Anzahl der Zeichen als auch der Zeichentyp ungültig sind, noch nicht implementiert. Wenn Sie versuchen, es so zu vervollständigen, wie es ist, erhöht sich die Menge an Code weiter.

[^ 1]: Genau genommen dient die Implementierung dieses Formulars fast ausschließlich der Verwendung der Validierungsfunktion von javax (ich habe keine eigene Validierung erstellt usw.), sodass es nicht erforderlich ist, es auf der Benutzerseite der Bibliothek gründlich zu testen. Wenn dabei etwas schief geht, liegt ein schwerwiegender Fehler in der Javax-Bibliothek selbst vor. Bitte denken Sie, dass es nur eine Unterkarte ist, um den Parametrisierungstest einführen zu wollen (lacht)

EchoFormTest.java



package com.example.form;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertNull;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;

@SpringBootTest
public class EchoFormTest {
	
	@Autowired
    Validator validator;

	private EchoForm testEchoForm = new EchoForm();
	private BindingResult bindingResult = new BindException(testEchoForm, "echoForm");
	
	/**
     *Normales System
     */
    @Test
    public void test_echo_Normales System_4 oder mehr Buchstaben() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("aaaa");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertNull(bindingResult.getFieldError());
    }

    @Test
    public void test_echo_Normales System_4 oder mehr Zahlen() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("1111");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertNull(bindingResult.getFieldError());
    }

    @Test
    public void test_echo_Normales System_4 oder mehr alphanumerische Zeichen() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("aa11");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertNull(bindingResult.getFieldError());
    }
    
    /**
     *Abnormale system_ unzureichende Anzahl von Zeichen
     */
    @Test
    public void test_echo_Anormales System_Englisch in halber Breite 3 Zeichen() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("aaa");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertThat(bindingResult.getFieldError().toString()).contains("Muss mindestens 4 Zeichen lang sein.");
    }
    
    @Test
    public void test_echo_Anormales System_3 Zeichen halber Breite() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("111");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertThat(bindingResult.getFieldError().toString()).contains("Muss mindestens 4 Zeichen lang sein.");
    }
    
    /**
     *Anormaler system_character-Typ ungültig
     */
    @Test
    public void test_echo_Anormales System_Hiragana() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("ah ah");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertThat(bindingResult.getFieldError().toString()).contains("Es sind nur alphanumerische Zeichen halber Breite gültig.");
    }
    
    @Test
    public void test_echo_Anormales System_Katakana() {
    	//Test-Vorbereitungen
    	testEchoForm.setName("Aaaaaaa");
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertThat(bindingResult.getFieldError().toString()).contains("Es sind nur alphanumerische Zeichen halber Breite gültig.");
    }
}

[× Schlechtes Beispiel (2)] Schleife das Datenmuster für die Anweisung

"Ich möchte nur die Testdaten mit demselben Code für die Testausführung und Ergebnisüberprüfung ändern ... Das ist es! Fügen Sie die Testdaten in ein Array ein und verwenden Sie die for-Anweisung, um die Ergebnisse für jede Daten auszuführen und zu überprüfen! ""

Wenn Sie das Java-Einführungsbuch lesen, ist es leicht zu glauben, dass redundante Beschreibungen in der Regel für Anweisungen gelöst werden. Es kann nicht geholfen werden. Bitte sagen Sie nein (← erfahrene Person).

Code, der auf den ersten Blick gut aussieht ... Für einen Satz, der kürzer als [△ schlechtes Beispiel ①] beschrieben werden kann ... Und wissen Sie, was an diesem Code falsch ist, der alles durchläuft, auch wenn Sie ihn tatsächlich in JUnit ausführen? ↓

EchoFormTest.java


   /**
     *Normales System
     */
    @Test
    public void test_echo_Normales System() {
    	String[] data = {"aaaa", "aa11", "1111"};
    	for(String testCase: data) {
    		//Test-Vorbereitungen
    		testEchoForm.setName(testCase);	
    		//Testimplementierung
    		validator.validate(testEchoForm, bindingResult);
    		//Ergebnisüberprüfung
    		assertNull(bindingResult.getFieldError());
    	}
    }

In diesem Beispiel ist es tatsächlich gut, wenn alle Testdaten normal enden. Wenn der Test jedoch mit den Daten in der Mitte fehlschlägt, schlägt der Test fehl, ohne dass die nachfolgenden Testdaten ausgeführt werden. Nicht alle Daten können getestet werden.

Wenn Sie beispielsweise versuchen, einen Fehler im zweiten und dritten der drei Daten zu verursachen, wie unten gezeigt ...

EchoFormTest.java


    /**
     *Normales System
     */
    @Test
    public void test_echo_Normales System() {
    	String[] dataPattern = {"aaaa", "err", "bad"}; //Err besteht diesen Test nicht, da 3 Zeichen oder weniger zu einem Fehler führen
    	for(String testData: dataPattern) {
    		//Test-Vorbereitungen
    		testEchoForm.setName(testData);	
    		//Testimplementierung
    		validator.validate(testEchoForm, bindingResult);
    		//Ergebnisüberprüfung
    		assertNull(bindingResult.getFieldError());
    	}
    }

Da der Test mit den zweiten Daten fehlschlägt, zeigt das Protokoll nur den zweiten Fehler an. Da die dritten und nachfolgenden Daten überhaupt nicht getestet werden, kann nicht festgestellt werden, ob die nachfolgenden Daten normal oder abnormal sind.

スクリーンショット 2020-09-22 15.33.30.png

org.opentest4j.AssertionFailedError: expected: <null> but was: <Field error in object 'echoForm' on field 'name': rejected value [err]; codes [Size.echoForm.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [echoForm.name,name]; arguments []; default message [name],2147483647,4]; default message [Muss mindestens 4 Zeichen lang sein.]>
	at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
	at org.junit.jupiter.api.AssertNull.failNotNull(AssertNull.java:48)
	at org.junit.jupiter.api.AssertNull.assertNull(AssertNull.java:37)
	at org.junit.jupiter.api.AssertNull.assertNull(AssertNull.java:32)
	at org.junit.jupiter.api.Assertions.assertNull(Assertions.java:258)
	at com.example.form.EchoFormTest.test_echo_Normales System(EchoFormTest.java:97)

Es wäre beängstigend zu glauben, dass es danach 100 oder 200 Datenmuster geben würde. Egal wie redundant es ist, [△ schlechtes Beispiel ①] kann seine Verantwortung als Testcode erfüllen und nicht dieses [× schlechte Beispiel ②]. Man kann also sagen, dass es immer noch besser ist.

[◎ Gutes Beispiel] Implementiert durch Parametrisierungstest

Tut mir leid, dass ich dich warten ließ! Hier ist ein gutes Beispiel. Implementierung im parametrisierten Test.

EchoFormTest.java


    /**
     *Normales System
     */
    @ParameterizedTest
    @ValueSource(strings = {"aaaa", "aa11", "1111"})
    public void test_echo_Normales System(String s) {
        //Test-Vorbereitungen
    	testEchoForm.setName(s);	
    	//Testimplementierung
    	validator.validate(testEchoForm, bindingResult);
    	//Ergebnisüberprüfung
    	assertNull(bindingResult.getFieldError());
    }

Es gibt keinen redundanten Code wie [△ schlechtes Beispiel ①]. Das Gute an der Parametrisierung ist außerdem, dass sie die Probleme von "nachfolgende Tests werden nicht durchgeführt" und "Ich weiß nicht, welche Testdaten durchgeführt wurden" löst, die ich in [× Schlechtes Beispiel (2)] gesehen habe. Anhand der folgenden Ausführungsergebnisse können Sie erkennen, dass alle drei Testdaten normal abgeschlossen wurden.

スクリーンショット 2020-09-22 15.56.07.png

Erhöhen Sie außerdem die Daten und prüfen Sie, ob die ersten und vierten Daten normal und die zweiten und dritten Daten falsch sind.

EchoFormTest.java


    /**
     *Normales System
     */
    @ParameterizedTest
    @ValueSource(strings = {"aaaa", "err", "bad", "1111"}) //err und bad sind keine Charaktere
    public void test_echo_Normales System(String s) {
        //Test-Vorbereitungen
    	testEchoForm.setName(s);	
    	//Testimplementierung
    	validator.validate(testEchoForm, bindingResult);
    	//Ergebnisüberprüfung
    	assertNull(bindingResult.getFieldError());
    }

スクリーンショット 2020-09-22 16.03.07.png

Selbst nachdem der zweite Fehler aufgetreten war, wurden die dritten und vierten Daten ordnungsgemäß überprüft, und die Stapelverfolgung wurde für jeden Fehler ausgegeben! JUnit5 ist zu bequem ...

Ich werde auch ein Beispiel für ein abnormales System veröffentlichen.

EchoFormTest.java


    /**
     *Abnormale system_ unzureichende Anzahl von Zeichen
     */
    @ParameterizedTest
    @ValueSource(strings = {"aaa", "111", "aa1"})
    public void test_echo_Anormales System_Unzureichende Anzahl von Zeichen(String s) {
    	//Test-Vorbereitungen
    	testEchoForm.setName(s);
    	//Testimplementierung
        validator.validate(testEchoForm, bindingResult);
        //Ergebnisüberprüfung
        assertThat(bindingResult.getFieldError().toString()).contains("Muss mindestens 4 Zeichen lang sein.");

Ich konnte dies ohne Probleme überprüfen!

スクリーンショット 2020-09-22 16.18.04.png

Bitte beachten Sie auch das folgende Qiita (ich habe es diesmal als Referenz verwendet!). Der Parametrisierungstest für JUnit 5 ist sehr praktisch

Es wird ein Zufall sein, aber im Fall von JUnit 4 wird die folgende Seite hilfreich sein. https://javaworld.helpfulness.jp/post-81/ Ich habe es mit "@RunWith (Parameterized.class)" implementiert. Obwohl die Codemenge größer als die von JUnit5 ist, kann der Parametrisierungstest in JUnit4 ausreichend implementiert werden. Es kann auch mit einem anderen Testläufer verwendet werden, indem es als innere Klasse von "@ RunWith (Enclosed.class)" erstellt wird.

abschließend

Diesmal haben wir uns den Parametrisierungstest in JUnit 5 angesehen. Ein schlechtes Beispiel ist, wie ich es tatsächlich geschrieben habe, als ich die Existenz des parametrisierten Tests selbst nicht kannte ... Es ist eigentlich einfach, einen Test mit einer for-Anweisung zu erstellen. Wenn Sie dies getan haben, sollten Sie in Betracht ziehen, zu einem parametrisierten Test zu wechseln!

Danke fürs Lesen!

Recommended Posts

[JUnit 5] Schreiben Sie einen Validierungstest mit Spring Boot! [Parametrisierungstest]
[JUnit 5-kompatibel] Schreiben Sie einen Test mit JUnit 5 mit Spring Boot 2.2, 2.3
Ich habe jetzt einen Test mit Spring Boot + JUnit 5 geschrieben
Formularklassenvalidierungstest mit Spring Boot
So schreiben Sie einen Komponententest für Spring Boot 2
Schreiben Sie den Testcode mit Spring Boot
Erhalten Sie Validierungsergebnisse mit Spring Boot
Testen Sie den Spring Framework Controller mit Junit
Führen Sie einen Transaktionsbestätigungstest mit Spring Boot durch
Beispielcode zum Testen eines Spring Boot-Controllers mit MockMvc
Schreiben wir einen Testcode für die Anmeldefunktion mit Spring Boot
Erstellen Sie eine Website mit Spring Boot + Gradle (jdk1.8.x)
Testen Sie den Controller mit Mock MVC im Spring Boot
Erstellen Sie mit Spring Boot eine einfache Such-App
Schreiben Sie schnell RestController-Tests mit Spring Boot + Spock
[Java] Hallo Welt mit Java 14 x Spring Boot 2.3 x JUnit 5 ~
[Java] Artikel zum Hinzufügen einer Validierung mit Spring Boot 2.3.1.
Erstellen Sie einen Web-API-Server mit Spring Boot
Erstellen Sie mit Docker eine Spring Boot-Entwicklungsumgebung
Selbstgemachte Validierung mit Spring
Machen Sie einen Unit-Test mit Junit.
Mit Spring Boot herunterladen
So führen Sie UT mit Excel als Testdaten mit Spring Boot + JUnit5 + DBUnit durch
Implementieren Sie eine einfache Rest-API mit Spring Security mit Spring Boot 2.0
Ein Memorandum beim Erstellen eines REST-Service mit Spring Boot
Erstellen Sie mit Spring Security 2.1 eine einfache Demo-Site mit Spring Security
Generieren Sie mit Spring Boot einen Barcode
Hallo Welt mit Spring Boot
Testen Sie die Web-API mit junit
Beginnen Sie mit Spring Boot
Hallo Welt mit Spring Boot!
Führen Sie LIFF mit Spring Boot aus
SNS-Login mit Spring Boot
Spring Boot beginnend mit Docker
Hallo Welt mit Spring Boot
Setzen Sie Cookies mit Spring Boot
Verwenden Sie Spring JDBC mit Spring Boot
Modul mit Spring Boot hinzufügen
Erste Schritte mit Spring Boot
Erstellen Sie mit Spring Boot einen Mikrodienst
Frühlingstest zur Überprüfung einzelner Artikel
Mail mit Spring Boot verschicken
Ändern Sie die Spring Boot-Validierungsnachricht
Eine Geschichte voller Grundlagen von Spring Boot (gelöst)
Erstellen wir eine einfache API mit EC2 + RDS + Spring Boot ①
Implementieren Sie eine einfache Rest-API mit Spring Security & JWT mit Spring Boot 2.0
Verwenden Sie Spring Test + Mockito + JUnit 4 für Spring Boot + Spring Retry Unit Test
Implementieren Sie einen einfachen Web-REST-API-Server mit Spring Boot + MySQL
Verwenden Sie die Standardauthentifizierung mit Spring Boot
Erstellen wir eine Buchverwaltungs-Webanwendung mit Spring Boot part1
Schreiben Sie einen reaktiven Server mit Micronaut
gRPC auf Spring Boot mit grpc-spring-boot-Starter
Hot Deploy mit Spring Boot-Entwicklung
Lassen Sie uns mit Spring Boot part3 eine Webanwendung für die Buchverwaltung erstellen
Spring Boot Programmierung mit VS Code
Bis "Hallo Welt" mit Spring Boot
Erstellen Sie eine Anfrage-App mit Spring Boot
Lassen Sie uns mit Spring Boot part2 eine Webanwendung für die Buchverwaltung erstellen
Ich habe ein einfaches Suchformular mit Spring Boot + GitHub Search API erstellt.
(Intellij) Hallo Welt mit Spring Boot
Erstellen Sie eine App mit Spring Boot