Grundlegende jUnit Fragen

8

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 )

%Vor%

Ich habe die Implementierung durchgeführt und eine Testklasse mit den folgenden Testfällen erstellt, die den Eingabe-String-Parameter als

enthalten
  1. gültige Nummern
  2. Zeichen
  3. Spezialsymbol
  4. leere Zeichenfolge
  5. Nullwert
  6. 0
  7. Negative Zahl
  8. float
  9. Grenzwerte
  10. Nummern, die gültig sind, aber deren Produkt außerhalb der Reichweite liegt
  11. Zahlen werden + Zeichen (+23)

Jetzt sind meine Fragen:

  1. 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?

  2. 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

  3. 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?

  4. Sind die oben genannten 11 Testfälle ausreichend? Habe ich etwas verpasst? Habe ich übertrieben? Wann ist genug?

  5. Habe ich die obige multiply () -Methode erfolgreich getestet?

Epitaph 26.04.2010, 00:35
quelle

6 Antworten

4

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.

    
Stephen C 26.04.2010, 02:31
quelle
6

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):

  • Ein Komponententest, der besteht, garantiert nicht , dass Ihr Code funktioniert

Denken Sie so darüber nach:

  • Ein Komponententest, der fehlschlägt, beweist, dass Ihr Code beschädigt ist

Es ist wirklich wichtig, dies zu realisieren.

Zusätzlich dazu:

  • Es ist normalerweise unmöglich, alle möglichen Eingaben zu testen

Und dann, wenn Sie refactoring:

  • Wenn alle Unit-Tests bestanden werden, bedeutet nicht , dass Sie keine Regression eingeführt haben

Aber:

  • Wenn einer Ihrer Komponententests fehlschlägt, wissen Sie, dass Sie eine Regression eingeführt haben

Das ist wirklich grundlegend und sollte Einheitentests 101 sein.

    
SyntaxT3rr0r 26.04.2010 03:07
quelle
5

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. :)

    
Bill the Lizard 26.04.2010 01:01
quelle
2

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.

    
fastcodejava 26.04.2010 02:50
quelle
2

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:

  • Vertrauen in Ihren Code - Sie haben einen hohen Sicherheitsgrad, dass Ihr Code korrekt ist.
  • Vertrauen zu Refactor - Sie können Ihren Code umgestalten und wissen, dass, wenn Sie etwas kaputt machen, Ihre Tests es Ihnen sagen.
  • Regressionen - Sie werden sofort wissen, wenn eine Änderung in einem Teil des Systems diese bestimmte Methode unbeabsichtigt bricht.
  • Vollständigkeit - Die Tests haben Sie gezwungen, über die möglichen Eingaben nachzudenken, die Ihre Methode erhalten kann, und wie die Methode darauf reagieren sollte.

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.

    
Jim Hurne 26.04.2010 01:13
quelle
1

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.

    
Gabriel Ščerbák 26.04.2010 16:40
quelle

Tags und Links