Ich habe eine String-Multiplikatorklasse mit einer multiply()
-Methode getestet, die 2 Zahlen als Eingaben akzeptiert (als String
) und die Ergebnisnummer zurückgibt (als String
)
Ich habe die Implementierung durchgeführt und eine Testklasse mit den folgenden Testfällen erstellt, die den Eingabe-String-Parameter als
enthaltenJetzt sind meine Fragen:
Ich würde gerne wissen, ob "jeder" assertEquals () in seiner eigenen Testmethode sein sollte? Oder kann ich ähnliche Testfälle wie testInvalidArguments () so gruppieren, dass sie alle Behauptungen enthalten, die ungültige Zeichen enthalten, da ALLE dieselbe NumberFormatException werfen?
Wenn ich einen Eingabewert wie ein Zeichen ("a") testen muss, muss ich Testfälle für ALLE Szenarien einschließen? "a" als erstes Argument "a" als zweites Argument "a" und "b" als die 2 Argumente
Nach meinem Verständnis besteht der Vorteil dieser Komponententests darin, Fälle herauszufinden, in denen die Eingabe eines Benutzers fehlschlagen und zu einer Ausnahme führen kann. Und dann können wir dem Benutzer statt einer Ausnahme eine aussagekräftige Nachricht geben (um sie zu bitten, eine gültige Eingabe zu liefern). Ist das richtig? Und, ist es der einzige Vorteil?
Sind die oben genannten 11 Testfälle ausreichend? Habe ich etwas verpasst? Habe ich übertrieben? Wann ist genug?
Habe ich die obige multiply () -Methode erfolgreich getestet?
1) Es gibt einen Kompromiss zwischen der Granularität der Tests (und daher der Einfachheit der Diagnose) und der Ausführlichkeit des Testcodes für die Einheit. Ich bin persönlich froh, relativ grobkörnige Testmethoden zu wählen, besonders nachdem sich die Tests und der getestete Code stabilisiert haben. Das Granularitätsproblem ist nur relevant, wenn Tests fehlschlagen. (Wenn ich in einem Multi-Assertion-Testfall einen Fehler erhalte, repariere ich entweder den ersten Fehler und wiederhole ihn, oder ich hacke temporär den Testfall, um herauszufinden, was passiert.)
2) Verwenden Sie Ihren gesunden Menschenverstand. Basierend auf Ihrem Verständnis, wie der Code geschrieben ist, entwerfen Sie Ihre Tests, um alle qualitativ verschiedenen Unterfälle auszuprobieren. Erkennen Sie, dass es unmöglich ist , alle möglichen Eingaben in allen bis auf die einfachsten Fälle zu testen.
3) Die Einheitsprüfung soll sicherstellen, dass die zu testenden Methoden das tun, was sie tun müssen. Was das bedeutet, hängt vom getesteten Code ab. Wenn ich zum Beispiel eine Unit sort
-Methode teste, ist die Validierung von Benutzereingaben irrelevant.
4) Die Abdeckung erscheint angemessen. Ohne eine genaue Beschreibung dessen, was Ihre Klasse zu tun hat, und eine Untersuchung der tatsächlichen Komponententests ist es jedoch unmöglich zu sagen, ob Sie alles abgedeckt haben. Zum Beispiel soll Ihre Methode mit führenden / nachgestellten Leerzeichen, Zahlen mit Dezimalpunkten, Zahlen wie "123.456", Zahlen mit nicht-lateinischen Ziffern, Zahlen in der Basis 42 umgehen?
5) Definieren Sie "erfolgreich getestet". Wenn Sie meinen, beweisen meine Tests, dass der Code keine Fehler hat, dann ist die Antwort ein definitives "NEIN". Sofern die Unit-Tests nicht jede mögliche Eingabe aufzählen, können sie keinen Beweis für die Richtigkeit darstellen. (In manchen Fällen reicht es nicht aus, alle Eingaben zu testen.)
In allen bis auf die einfachsten Fälle kann das Testen keine Fehler nachweisen. Das einzige, was es beweisen kann, ist, dass Fehler vorhanden sind. Wenn Sie beweisen müssen, dass ein Programm keine Fehler hat, müssen Sie auf "formale Methoden" zurückgreifen; d. h. Anwendung formaler Theorembeweistechniken auf Ihr Programm.
Und wie eine andere Antwort darauf hinweist, müssen Sie es echten Benutzern geben, um zu sehen, was sie mit unerwarteten Eingaben erreichen könnten. Mit anderen Worten ... ob die angegebenen oder abgeleiteten Benutzeranforderungen tatsächlich vollständig und gültig sind.
Das Komponententesten ist großartig (in dem 200 KLOC Projekt, das ich arbeite, habe ich so viele Unit Test Codes wie regulärer Code), aber (unter der Annahme eines korrekten Komponententests):
Denken Sie so darüber nach:
Es ist wirklich wichtig, dies zu realisieren.
Zusätzlich dazu:
Und dann, wenn Sie refactoring:
Aber:
Das ist wirklich grundlegend und sollte Einheitentests 101 sein.
1) Ich denke, es ist eine gute Idee, die Anzahl der Assertionen in jedem Test zu begrenzen. JUnit meldet nur den ersten Fehler in einem Test. Wenn Sie mehrere Assertionen haben, können einige Probleme maskiert sein. Es ist nützlicher, alles zu sehen, was passiert ist und alles, was fehlgeschlagen ist. Wenn Sie in einem Test 10 assertEquals
haben und der erste fehlschlägt, dann wissen Sie einfach nicht, was mit den anderen 9 passiert wäre. Das wären gute Datenpunkte beim Debuggen.
2) Ja, Sie sollten Tests für alle Ihre Eingaben einschließen.
3) Es muss nicht nur die Endbenutzereingabe getestet werden. Sie sollten Tests für alle öffentlichen Methoden schreiben, die möglicherweise fehlschlagen. Dafür gibt es einige gute Richtlinien, insbesondere zu Getter und Setter, in den JUnit FAQ .
>4) Ich denke, Sie haben es ziemlich gut abgedeckt. (Zumindest kann ich an nichts anderes denken, aber sieh # 5).
5) Geben Sie es einigen Benutzern zum Testen. Sie finden immer Stichprobendaten, die ich nie testen würde. :)
Wahre Anzahlen von Tests sind natürlich unendlich. Das ist nicht praktisch. Sie müssen gültige repräsentative Fälle auswählen. Du scheinst das getan zu haben. Gute Arbeit.
1) Es ist am besten, Ihre Tests klein und fokussiert zu halten. Wenn ein Test fehlschlägt, ist klar, warum der Test fehlgeschlagen ist. Dies führt normalerweise zu einer einzelnen Assertion pro Test, aber nicht immer.
Statt jedoch einen Test für jedes einzelne "ungültige Szenario" von Hand zu kodieren, sollten Sie sich JUnit 4.4-Theorien ansehen (siehe Release-Informationen zu JUnit 4.4 und dieser Blogpost ) oder der JUnit parametrisierten Test-Runner.
Parametrisierte Tests und Theorien sind perfekt für "Berechnungsmethoden" wie diese. Um die Dinge in Ordnung zu halten, mache ich außerdem zwei Testklassen, eine für "gute" Eingaben und eine für "schlechte" Eingaben.
2) Sie müssen nur die Testfälle einbeziehen, von denen Sie denken, dass sie am ehesten Fehler in Ihrem Code aufdecken, nicht alle möglichen Kombinationen aller Eingaben (das wäre unmöglich, wie WizardOfOdds in seinen Kommentaren darauf hinweist). Die drei Sätze, die du vorgeschlagen hast, sind gut, aber ich würde wahrscheinlich nicht mehr als diese drei testen. Mithilfe von Theorien oder parametrisierten Tests können Sie jedoch noch weitere Szenarien hinzufügen.
3) Schreibgeräte-Tests haben viele Vorteile, nicht nur die, die Sie erwähnen. Einige andere Vorteile umfassen:
5) Es hört sich so an, als hätten Sie mit den möglichen Testszenarien gute Arbeit geleistet. Ich denke, du hast alle wichtigen.
Ich möchte nur hinzufügen, dass mit Komponententests Sie noch mehr gewinnen können, wenn Sie zuerst über die möglichen Fälle nachdenken und danach in der testgetriebenen Entwicklungsweise implementieren, denn dies wird Ihnen helfen, sich auf den aktuellen Fall zu konzentrieren und Dies ermöglicht es Ihnen, die einfachste Implementierung DRY-fähig zu gestalten. Sie könnten auch ein Testüberprüfungswerkzeug verwenden, z. in Eclipse EclEmma, das wirklich einfach zu bedienen ist und Ihnen zeigen wird, ob Tests Ihren gesamten Code ausgeführt haben, was Ihnen helfen könnte festzustellen, wann es genug ist (obwohl dies kein Beweis, sondern nur eine Metrik ist). Generell, wenn es um Unit-Tests geht, war ich sehr inspiriert von Kent Becks Test Driven Development by Example Buch, ich empfehle es sehr.
Tags und Links java unit-testing junit