Wenn Sie nur eine Aussage pro Test haben sollten; Wie teste ich mehrere Eingänge?

15

Ich versuche, einige Testfälle aufzubauen, und habe gelesen, dass Sie versuchen sollten, die Anzahl der Zusicherungen pro Testfall zu begrenzen.

Meine Frage ist also, wie man am besten eine Funktion mit mehreren Eingängen testet. Zum Beispiel habe ich eine Funktion, die eine Zeichenfolge vom Benutzer analysiert und die Anzahl der Minuten zurückgibt. Die Zeichenfolge kann in der Form vorliegen "5w6h2d1m", wobei w, h, d, mdie Anzahl der Wochen, Stunden, Tage und Minuten entspricht.

Wenn ich der Aussage "1 Assertion pro Testregel" folgen wollte, müsste ich für jede Variation der Eingabe mehrere Tests durchführen. Das kommt mir albern vor, stattdessen habe ich nur so etwas wie:

self.assertEqual(parse_date('5m'), 5)
self.assertEqual(parse_date('5h'), 300)
self.assertEqual(parse_date('5d') ,7200)
self.assertEqual(parse_date('1d4h20m'), 1700)

In dem einen Testfall. Gibt es einen besseren Weg?

speg
quelle
Der beste Weg, dies zu tun, ist die Verwendung von Parametern (einige Frameworks unterstützen diese Funktion, alle Frameworks sollten dies tun). Auf diese Weise testen Sie ein einzelnes Verhalten, berücksichtigen jedoch viele Testfälle und können weiterhin feststellen, welche Parameterwerte im Fehlerfall einen Fehler verursacht haben
Kemoda,

Antworten:

23

Eine pragmatischere Methode zum Anzeigen einer Aussage pro "Testregel" besteht darin, dass Ihre Aussagen in einem einzigen Test ein einziges Konzept abdecken.

Auf diese Weise testen Sie immer noch ein einzelnes Konzept in einem einzelnen Test. In Ihrem Fall, ob Ihre Eingabezeichenfolge in einem einzelnen Datum korrekt analysiert wird.

Sie sollten von Fall zu Fall entscheiden, ob Sie ein einzelnes Konzept mit mehreren Asserts oder ein einzelnes Assert in mehreren Tests besser testen können.

Wählen Sie die Option, die klarere Tests und weniger Wiederholungen ermöglicht, während Ihre Tests immer noch in der Lage sind, verschiedene Fehlerquellen in Ihrer Methode hervorzuheben. Sie möchten, dass klar ist, wann ein Test genau fehlschlägt, was passiert ist, anstatt den Test zu debuggen, um herauszufinden, was schief gelaufen ist.

Gilles
quelle
17

Es hängt sehr stark von Ihrer Testbibliothek ab. In der C # -Bibliothek NUnit können Sie Folgendes tun:

[TestCase('5m', 5)]
[TestCase('5h', 300)]
[TestCase('5d', 7200)]
[TestCase('1d4h20m', 1700)]
public void ParseDateTest(inputString, expectedMinutes)
{
    Assert.That(parse_date(inputString), Is.EqualTo(expectedMinutes));
}
Scroog1
quelle
In Java mit testng haben Sie @ DataProvider Methoden
Kemoda
das ist meiner Meinung nach die beste Lösung. In fast jeder Sprache können Sie Ihre Tests parametrisieren. für Java: @Parameterized , JunitParams , Zohhak
piotrek
3

Ja, machen Sie mehrere Tests für jede Variation der Eingabe.

Das Hauptziel einer Aussage pro Testrichtlinie ist (im Idealfall), dass ein Fehler zu einem Testfehler führt und umgekehrt, sodass Sie genau wissen, was fehlgeschlagen ist. Dann können Sie mit einem sehr genauen Test arbeiten, um die Grundursache zu debuggen und zu überprüfen. Sie können dies mit einer Behauptung aufheben und Sie können mit mehreren Behauptungen einverstanden sein. In diesem speziellen Szenario hätte ich einen Test für jedes Suffix und einige Kombinationen von Bestellungen.

Hoffentlich ist klar, warum das Isolieren von Tests von Vorteil ist: Sie verschwenden weniger Zeit beim Debuggen, wenn etwas schief geht. Wenn Sie wirklich sicher sind, dass der Test wahrscheinlich nicht fehlschlägt und der Aufwand für das Durchsuchen des Tests gering ist, ist es möglicherweise sinnvoll, sie alle gleichzeitig zu testen, um Implementierungszeit zu sparen.

Die Geschichte hat jedoch gezeigt, dass es sich niemals lohnt , ein wenig Zeit beim Schreiben von Code auf Kosten des Lesens / Verwendens von Code zu sparen . Daher die Richtlinie.

Telastyn
quelle
1

Puristen würden sagen, dass Aussagen für unterschiedliche Eingabewerte in separate Testmethoden innerhalb der Testklasse gestellt werden sollten. Ein Grund dafür ist, dass es abhängig von Ihrer Testbenutzeroberfläche oft einfacher ist, zwischen einzelnen Testfehlern als zwischen einzelnen Behauptungen zu unterscheiden, wodurch Sie die Fehlerquelle möglicherweise schneller identifizieren können.

Beim Testen mit JUnit können wir dies umgehen, indem wir die Version der assert * -Methoden mit einem anfänglichen String-Argument verwenden, um eine Assertion innerhalb derselben Testmethode von einer anderen zu unterscheiden.

self.assertEqual("just minutes", parse_date('5m'), 5)
self.assertEqual("just hours", parse_date('5h'), 300)
self.assertEqual("just days", ('5d') ,7200)
self.assertEqual("days, hours, minutes", parse_date('1d4h20m'), 1700)
Mike Partridge
quelle