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.
Unit-Tests können das Verhalten einer Funktion nur durch Assertion überprüfen.
Manuelle Tests sind der effizienteste Weg, um unbekannte Fehler zu finden.
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.
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.
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.
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.
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.
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;
}
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.
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.
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.
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.
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".
Ich denke, hier gibt es einige Regeln.
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.
@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.
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.
Das war alles.
Recommended Posts