[JAVA] Ich möchte einen Unit Test schreiben!

Die Gewohnheit, Unit-Tests zu schreiben

Insbesondere, bis Sie die App, die Sie entwickeln, erstellen und bereitstellen und auf dem Bildschirm sehen können Es dauert 5 Minuten und 10 Minuten, aber in diesem Fall Das Schreiben der Geschäftslogik, aber das manuelle Testen erzeugt nur Schmerzen.

In diesem Artikel, Ich weiß, dass es besser ist, es irgendwie zu schreiben, aber ehrlich gesagt weiß ich nicht, wie ich es mit der aktuellen Struktur schreiben soll. Für Entwickler, die nicht so viel ausgeben möchten, weil sie nicht wissen, worüber sie sich freuen. Es bietet eine Entwurfsmethode zum effektiven Schreiben von Komponententests mit xUnit.

Grundsätzlich ist es Java8 und JUnit4, aber der Inhalt ist in der Sprache nicht so eingeschränkt.

Hauptprämisse

Unit Test ist kein "Test"

Unit-Tests können das Verhalten einer Funktion nur durch Assertion überprüfen.

Manuelle Tests sind der effizienteste Weg, um unbekannte Fehler zu finden.

Unit Testing ist ein Werkzeug zur Unterstützung der Entwicklung

Anstatt die Qualität zu verbessern, ist es möglich, die Mindestprüfungen automatisch durchzuführen, damit die Entwicklungsgeschwindigkeit durch Langeweile verlangsamt wird und später keine unerwarteten Nacharbeiten auftreten.

Offensichtlich richtet sich dieser Artikel an Personen, die normalerweise keine Komponententests schreiben, also nur für den Fall.

Vorteile des Schreibens eines Komponententests

Nacharbeit ist auf der Vorderseite

Wie im obigen Beispiel dauert es 5 Minuten und 10 Minuten, um vom Bildschirm aus überprüfen zu können, aber in diesem Fall Bei komplexer Geschäftslogik ist es effizienter, vor dem Testen auf dem Bildschirm eine Nacharbeit zu generieren.

Mit Unit-Tests können Sie die Ergebnisse im Allgemeinen schneller anzeigen, als Sie den Server starten und auf dem Bildschirm anzeigen können. Als Name der Einheit (Einheit) Test ist es auch möglich, auf der Ebene jeder Funktion zu überprüfen, bevor alle Funktionen verbunden werden. Ein weiterer Grund ist, dass die Implementierungszeit => Validierungszeitverzögerung geringer ist.

Mit anderen Worten

In diesen beiden Punkten kann eine Nacharbeit schnell erkannt werden.

Spezifikationen können beschrieben werden

Oft als Verdienst von TDD erwähnt, Unit-Tests werden normalerweise in Form von Zusicherungen geschrieben (z. B. sollte der Rückgabewert der Funktion XX ZZ sein, wenn das Argument YY ist). Dies ermöglicht nachfolgenden Entwicklern das ** erfolgreiche Schreiben ** durch Lesen des Testcodes für den Komponententest. Sie werden am deutlichsten wissen können, dass "diese Funktion solche Spezifikationen hat".

(Gut schreiben ist sehr wichtig, Es ist ziemlich verwirrend, wenn es nicht sowohl Vollständigkeit als Testfall als auch Lesbarkeit als Code aufweist.)

Natürlich können Entwickler das nicht nur verstehen. Wenn ein Entwickler, der die Funktion nicht versteht, eine schlechte Änderung vornimmt, Solange sich das CI richtig dreht Im Unit-Test kann automatisch festgestellt werden, dass sich "das Verhalten gegenüber den gewünschten Spezifikationen geändert hat".

Die ordnungsgemäße Wartung von Unit-Tests ist Dies führt dazu, dass Fehler automatisch erkannt werden können, die sonst nur in der Phase des Integrationstests bemerkt würden.

Leicht verständliche Benutzerfreundlichkeit öffentlicher Funktionen

Dies wird auch oft als Vorteil von TDD angeführt, Der Testcode ist der erste Benutzer der (geplanten) öffentlichen Funktion, die Sie implementieren.

Insbesondere in Java denke ich persönlich, dass das Signaturdesign verschiedene Faktoren wie Skalierbarkeit und Änderungsrisiko bestimmt. Durch tatsächliches Aufrufen der Funktion aus dem Testcode ist es häufig möglich, die Verwendbarkeit der Funktion wiederherzustellen.

Wenn Sie dies bemerken, nachdem es aus verschiedenen Klassen aufgerufen wurde, sind das Risiko und der Umfang der Änderungen enorm.

Kann verboten testen

Bei einem Kombinationstest gibt es ein Verbot. Der Punkt ist, dass Werte, die tatsächlich nicht über den Bildschirm eingegeben werden können, als verbotene Regel aus dem Testfall ausgeschlossen werden. In diesem Fall ist das Urteil "Sie können nicht vom Bildschirm aus eingeben" unzuverlässig.

Zum Beispiel, selbst wenn das Frontend validiert ist, Es ist nicht sinnvoll, wenn der Wert zum Zeitpunkt des Sendens von einem böswilligen Benutzer neu geschrieben wird.

Da der Komponententest nicht die Einschränkung hat, dass er eingegeben oder nicht über den Bildschirm eingegeben werden kann, Auch für Eingabemuster, die verboten sind Es ist möglich zu testen.

Es wäre schön, einen Test schreiben zu können, der erwartet, dass eine Ausnahme ausgelöst wird.

Warum kann ich keinen Komponententest schreiben?

Nun, ich gab verschiedene Verdienste, Wenn Sie diesen Artikel, wie bereits erwähnt, lesen, ohne einen Komponententest zu schreiben, Ich habe jeden Tag Probleme mit umfangreichen Anwendungsentwicklungsarbeiten.

Warum ich es nicht geschrieben habe, warum meine Senioren um mich herum In Anbetracht dessen, dass niemand so weit das Auge reicht geschrieben hat Vielleicht tatsächlich Erstens kann dies daran liegen, dass der Produktcode eine Struktur aufweist, die das Schreiben von Komponententests erschwert.

In diesem Abschnitt: "Warum kann ich keinen Komponententest schreiben?" Ich werde die Merkmale erklären, wenn es schwierig ist, einen Komponententest zu schreiben.

Hier als gemeinsame Funktion an Ihrem Arbeitsplatz Stellen Sie sich etwas mit dem Namen "vollständig" vor, das für den Abschlussprozess von etwas verantwortlich ist.

public Map<String,Object> complete(BigBean bigBean) {
// ...
SomeKindOfConfig config = dao.loadConfig(someId);
this.computeSomeValue(bigBean);
if(config.getSomeAttribute() == 1) {
// ...
} else {
// ...
}
// ...
for(DtlBean dtl : bigBean.getManyDtls()) {
// ...
}
if(bigBean.getOtherAttribute() == 0) {
// ...
}
dao.updateSomething(bigBean);
return res;
}

Die Funktion ist zu lang und der erwartete Rückgabewert ist unklar

Wenn Sie etwas erledigen Ich denke, dass es üblich ist, ein funktionales Design zu erstellen, das bequem ist, da verschiedene Prozesse per Knopfdruck ausgeführt werden können. Es ist ein Muster, in dem sie alle in einer Funktion geschrieben sind.

Eine solche Verarbeitung wird oft durchgeführt Ich muss diese Einstellung später ausprobieren und den Prozess verzweigen! Weil es eine schwierige Situation sein kann Der DB-Zugriff ist ebenfalls chaotisch, z. B. wenn Sie unterwegs Ad-hoc eingeben.

Für Geschäftslogik, die sich wie dieses Erbe anfühlt Unit-Tests sind sehr schwer zu schreiben.

Es gibt verschiedene Probleme, außer zu lang zu sein. Wenn Sie es oft mit einer Funktion tun, Es ist schwierig, in Form einer Behauptung zu schreiben, dass "die Ausgabe für die Eingabe so sein sollte". Es ist ein großes Merkmal. Da es viele Zweige gibt und die Kombination explodiert, wird der Umfang der Testklassenbeschreibung enorm, was ineffizient ist.

Ich habe das Argument geändert

private void computeSomeValue(BigBean bigBean) {
//...
bigBean.setSomeValue(someValue);
//...
}

Wenn es eine void-Methode gibt, deren Argumentinhalt sich ändern kann Auf der anderen Seite Da es unmöglich wird, die Behauptung klar zu schreiben, dass "wenn es eine solche Eingabe gibt, sollte es als Ausgabe so sein". Ich denke, Sie sollten es so weit wie möglich vermeiden.

Wenn Sie die oben genannten Anforderungen wirklich erfüllen möchten, Die Unterschrift selbst,

private SomeValueClass computeSomeValue(BigBean bigBean) {
//...
return someValue;
}

Es ist besser so zu schreiben.

Kommt auf etwas anderes als Argumente an

Abhängig von der Funktionsweise des Unit-Tests, Wenn so etwas wie eine Testumgebung nicht für eine schnelle Aktualisierung bereit ist Zum Beispiel ist es nicht einfach, einen DB-Wert-abhängigen mit einem Unit-Test zu testen.

Im Fall des obigen Prozesses Ich werde unterwegs einen einstellungsähnlichen Wert von der DB erhalten. Dies führt zu einer vollständigen Methodenzusicherung für dasselbe Argument Abhängig vom Status der Datenbank ist dies erfolgreich oder schlägt fehl.

Erstens für nachfolgende Entwickler Ich denke, es ist eine schlechte Implementierung, plötzlich die Einstellungen auf dem Weg zu sehen.

In diesem Fall verspotten Sie Dao mit Mockito auf der Seite des Unit-Tests usw. Es gibt einen Weg, damit umzugehen.

Einfach zu schreibendes Unit-Test-Design

Angemessene Aufteilung

Eine Funktion der Komplexität, die die Kombination von Zweigen nicht explodiert. Wenn es separat in einem lose gekoppelten Zustand implementiert wird, Sie können Unit-Tests sehr effektiv implementieren und ausführen.

Angenommen, Sie haben die Möglichkeit, die Miete für mehrere Monate an einem Tag zu zahlen. Wir werden eine Vorschaufunktion implementieren, mit der Sie sehen können, wie viel Miete Sie im Monat zahlen werden.

Als Argument

Es wird____geben.

Als Ausgabe,

Angenommen, die Spezifikation lautet.

Wenn Sie versuchen, alles vom Bildschirm aus zu verbinden und normal zu drücken,

--Wenn es mehrere gibt? Wann ist es einzigartig?

Es gibt verschiedene Dinge, und es neigt dazu, als Kombination zuzunehmen.

Da es sich jedoch um eine Reihe einfacher Spezifikationen handelt, wenn diese geteilt werden, Wenn Sie einen Komponententest für "eine Funktion schreiben, die nur einen Monat formatiert" Sie können sehen, dass Sie dem Mondformat bis zu einem gewissen Grad vertrauen können. Wenn Sie eine Einheit "Funktion zum Sortieren mehrerer Monate" schreiben, Es ist nicht erforderlich, die Reihenfolge der "Funktionen, die ausgegeben werden, indem der Anfang mit dem Ende mehrerer Monate mit Bindestrichen verbunden wird" unermüdlich zu testen. Und "Vergleichen Sie das Datum und das Jahr und den Monat, und wenn das Jahr und der Monat früher sind," vor ", Wenn es einen Komponententest für "eine Funktion gibt, die" next "zurückgibt, wenn Jahr und Monat später sind", Der Komponententest der endgültigen Vorschau-Anzeigefunktion ist Sie müssen nur den repräsentativen Wert testen, damit sie richtig kombiniert werden.

Wenn Sie jedes als Set mit einem Unit-Test implementieren, der klein ist und einen Rückgabewert für das Argument garantiert, "Zumindest funktioniert es soweit richtig, nicht wahr?" Es gibt auch den Vorteil, dass Sie sich beruhigt entwickeln können, da Sie beim Überprüfen fortfahren können.

Referenztransparenz

An expression is said to be referentially transparent if it can be replaced with its corresponding value without changing the program's behavior. As a result, evaluating a referentially transparent function gives the same value for same arguments.

https://en.wikipedia.org/wiki/Referential_transparency

"Eine referenztransparente Funktion bedeutet, dass sich das Verhalten des Programms auch dann nicht ändert, wenn die Funktion durch ihren Rückgabewert ersetzt wird. Wenn Sie eine referenztransparente Funktion ausführen, gibt ** daher immer denselben Rückgabewert für dasselbe Argument ** zurück. ""

Schreiben Sie die Geschäftslogik, die Ihnen wichtig ist, in eine transparente Referenz. Persönlich bin ich froh, die Klasse mit dem Status klar von der Funktion zu trennen, die die Ausgabe für die Eingabe zurückgibt.

Es ist nicht nur einfach, einen Komponententest zu schreiben, sondern es ist auch einfach zu schreiben, wenn immer der gleiche Rückgabewert für das gleiche Argument zurückgegeben wird. Es macht den Unit-Test insofern effektiv, als es "die durch den Unit-Test garantierte Bewegung in jedem Zustand reproduziert".

Wie viel soll ich schreiben?

Grundsätzlich scheint es gut, für jede öffentliche Methode mindestens eine vorzubereiten

Ich denke, hier gibt es einige Regeln.

Effektives Schreiben

Testen Sie das Design schnell und richtig

Wenn Sie einen Komponententest als Beschreibung der Spezifikationen schreiben, Es kann jedoch kontraproduktiv sein, den Wert, der in die dunkle Wolke gelangt ist, weiterzugeben und eine Aussage zu treffen.

Zuallererst das Minimum

Es ist effektiv, einige der Methoden zu greifen, die normalerweise als Testmethoden bekannt sind.

Vielmehr im Fall einer Funktion, die mit diesen beiden nicht in den Fall gebracht werden kann Da der Test selbst im Unit-Test möglicherweise ungeeignet ist, Möglicherweise möchten Sie die Validierung mit anderen Methoden in Betracht ziehen.

Ermöglicht das Kombinieren und Ausführen von Entwurfsfällen

@Runwith(Theories.class)

Oder

@Runwith(Parameterized.class)

Sie können zum Testen verwenden, indem Sie mehrere "Sätze von Argumenten und erwarteten Werten" an einen Testcode übergeben. Kurz gesagt, Sie können die Ein- und Ausgänge umfassend und einfach zu schreiben machen.

Bereiten Sie eine Testsuite vor und drehen Sie sie mehrmals

Wenn die Anzahl der Testklassen zunimmt Erstellen Sie eine Suite-Klasse, die sie für jedes Paket bündelt. Lassen Sie uns jederzeit alle darunter liegenden Testklassen gleichzeitig aktivieren.

Wenn sich etwas ändert Wenn Sie alles sofort umdrehen, Solange dies im Unit-Test bestätigt wird, funktioniert es mit den bisherigen Spezifikationen. Sie können sofort sehen.

Für Projekte, die CI-Tools wie Jenkins und Travis betreiben Ich denke, es ist eine gute Idee, es umzudrehen, wenn Änderungen an die Codebasis übertragen werden.

Zusammenfassung

Warum einen Unit Test schreiben?

Warum kann ich noch keinen Komponententest schreiben?

Wie kann der Komponententest einfach geschrieben werden?

Das war alles.

Recommended Posts

Ich möchte einen Unit Test schreiben!
Ich möchte ein schönes build.gradle schreiben
Ich möchte eine einfache Wiederholung einer Zeichenkette schreiben
So schreiben Sie einen Komponententest für Spring Boot 2
[SpringBoot] So schreiben Sie einen Controller-Test
[Ruby] Ich möchte einen Methodensprung machen!
Ich möchte eine Struktur für die Ausnahmebehandlung entwerfen
Ich möchte schnell von Java nach SQLite schreiben
Ich möchte eine Methode einer anderen Klasse aufrufen
Ich möchte Zeichen konvertieren ...
Ich möchte ein kleines Symbol in Rails verwenden
Einführung in Micronaut 2 ~ Unit Test ~
Ich möchte eine bestimmte Datei mit WatchService überwachen
Ich möchte eine Funktion in der Rails Console definieren
So schreiben Sie ein benutzerorientiertes Programm (1)
Ich möchte in RSpec auf einen GoogleMap-Pin klicken
Ich möchte eine generische Anmerkung für einen Typ erstellen
Ich möchte der Kommentarfunktion eine Löschfunktion hinzufügen
Dynamisches Schreiben iterativer Testfälle mit test / unit (Test :: Unit)
[Java] Ich möchte ein Byte-Array in eine Hexadezimalzahl konvertieren
Ich möchte beim Schreiben von Testcode zufällig Informationen generieren
Ich möchte einen relativen Pfad in einer Situation finden, in der Pfad verwendet wird
Ich möchte eine Produktinformationsbearbeitungsfunktion ~ part1 ~ implementieren
Ich möchte ein bestimmtes Modell von ActiveRecord ReadOnly erstellen
Ich möchte eine Liste mit Kotlin und Java erstellen!
Ich möchte eine Methode aufrufen und die Nummer zählen
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Ich möchte ein Formular erstellen, um die Kategorie [Schienen] auszuwählen
Selbst in Java möchte ich true mit == 1 && a == 2 && a == 3 ausgeben
Ich möchte dem select-Attribut einen Klassennamen geben
Ich möchte eine Parkettdatei auch in Ruby erstellen
Ich möchte FireBase verwenden, um eine Zeitleiste wie Twitter anzuzeigen
[Java] Ich möchte Standardeingabe und Standardausgabe mit JUnit testen
So führen Sie einen Komponententest für Spring AOP durch
Ich möchte eine Schleife schreiben, die auf einen Index mit der Stream-API von Java 8 verweist
Ich möchte rekursiv nach Dateien in einem bestimmten Verzeichnis suchen
Ich möchte in der Lage sein, selbst reguläre Ausdrücke zu denken und zu schreiben. ..
Ich möchte eine Browsing-Funktion mit Ruby on Rails hinzufügen
Ich möchte Swipeback auf einem Bildschirm verwenden, der XLPagerTabStrip verwendet
Ich möchte nur Java mit Eclipse auf meinem Mac schreiben
Nur daran möchte ich mich erinnern, 4 Entwürfe zum Schreiben von Unit-Tests
Ich habe versucht, Code wie eine Typdeklaration in Ruby zu schreiben
Beispielcode zum Testen eines Spring Boot-Controllers mit MockMvc
Ich habe getestet, wie man Rubys Test / Gerät und Janken's Code verwendet.
Ich möchte mit einem regulären Ausdruck zwischen Zeichenketten extrahieren
Eine flüssige Schnittstelle? -Ich möchte Ihnen die Möglichkeit geben, guten Code zu schreiben. 3 [C # Refactoring Sample]
Ich möchte doppelte Fehlermeldungen beseitigen
Führen Sie RSpec ein und schreiben Sie den Unit-Test-Code
Ich möchte eine ios.android App machen