27 Stimmen

Wie sollten Unit-Tests dokumentiert werden?

Ich versuche, die Anzahl und Qualität der Tests in meinen Python-Projekten zu verbessern. Eine der Schwierigkeiten, auf die ich gestoßen bin, als die Anzahl der Tests zunahm, ist zu wissen, was jeder Test tut und wie er helfen soll, Probleme zu erkennen. Ich weiß, dass ein Teil der Nachverfolgung von Tests bessere Namen für Unit-Tests sind (was bereits angesprochen wurde anderswo ), aber ich bin auch daran interessiert zu verstehen, wie Dokumentation und Unit-Tests zusammenpassen.

Wie können Unit-Tests dokumentiert werden, um ihren Nutzen zu verbessern, wenn diese Tests in Zukunft fehlschlagen? Was macht einen guten Unit-Test-Docstring aus?

Ich würde sowohl beschreibende Antworten als auch Beispiele für Unit-Tests mit ausgezeichneter Dokumentation begrüßen. Obwohl ich ausschließlich mit Python arbeite, bin ich offen für Praktiken aus anderen Sprachen.

17voto

Kaleb Brasee Punkte 49955

Ich dokumentiere die meisten meiner Unit-Tests ausschließlich mit dem Methodennamen:

testInitializeSetsUpChessBoardCorrectly()
testSuccessfulPromotionAddsCorrectPiece()

Für fast 100 % meiner Testfälle erklärt dies eindeutig, was der Unit-Test überprüft, und das ist alles, was ich verwende. In einigen der komplizierteren Testfälle füge ich jedoch einige Kommentare in der Methode hinzu, um zu erklären, was mehrere Zeilen tun.

Ich habe schon einmal ein Tool gesehen (ich glaube, es war für Ruby), das Dokumentationsdateien erzeugt, indem es die Namen aller Testfälle in einem Projekt analysiert, aber ich erinnere mich nicht an den Namen. Wenn Sie Testfälle für eine Schachkönigin-Klasse hätten:

testCanMoveStraightUpWhenNotBlocked()
testCanMoveStraightLeftWhenNotBlocked()

würde das Tool ein HTML-Dokument mit folgendem Inhalt erstellen:

Queen requirements:
 - can move straight up when not blocked.
 - can move straight left when not blocked.

15voto

Mike Mazur Punkte 2459

Vielleicht liegt das Problem nicht darin, wie man am besten Testdokumente schreibt, sondern wie man die Tests selbst schreibt? Wenn man die Tests so umgestaltet, dass sie sich selbst dokumentieren, kann man viel erreichen, und die Dokumentation wird nicht veraltet sein, wenn sich der Code ändert.

Es gibt ein paar Dinge, die Sie tun können, um die Tests klarer zu machen:

  • eindeutige und beschreibende Bezeichnungen der Prüfmethoden (bereits erwähnt)
  • der Testkörper sollte klar und prägnant sein (selbstdokumentierend)
  • Abstrahieren von komplizierten Einstellungen/Abbau usw. in Methoden
  • mehr?

Zum Beispiel, wenn Sie einen Test wie diesen haben:

def test_widget_run_returns_0():
    widget = Widget(param1, param2, "another param")
    widget.set_option(true)
    widget.set_temp_dir("/tmp/widget_tmp")
    widget.destination_ip = "10.10.10.99"

    return_value = widget.run()

    assert return_value == 0
    assert widget.response == "My expected response"
    assert widget.errors == None

Sie können die Setup-Anweisungen durch einen Methodenaufruf ersetzen:

def test_widget_run_returns_0():
    widget = create_basic_widget()
    return_value = widget.run()
    assert return_value == 0
    assert_basic_widget(widget)

def create_basic_widget():
    widget = Widget(param1, param2, "another param")
    widget.set_option(true)
    widget.set_temp_dir("/tmp/widget_tmp")
    widget.destination_ip = "10.10.10.99"
    return widget

def assert_basic_widget():
    assert widget.response == "My expected response"
    assert widget.errors == None

Beachten Sie, dass Ihre Testmethode nun aus einer Reihe von Methodenaufrufen mit Namen besteht, die die Absicht offenbaren, eine Art DSL, die speziell für Ihre Tests gilt. Braucht ein solcher Test noch eine Dokumentation?

Außerdem ist zu beachten, dass Ihre Testmethode hauptsächlich auf einer Abstraktionsebene angesiedelt ist. Jemand, der die Testmethode liest, wird sehen, dass der Algorithmus ist:

  • Erstellen eines Widgets
  • Aufruf der Ausführung des Widgets
  • Sicherstellen, dass der Code das tut, was wir erwarten

Ihr Verständnis der Testmethode wird nicht durch die Details der Einrichtung des Widgets getrübt, das eine Abstraktionsebene niedriger ist als die Testmethode.

Die erste Version der Prüfmethode folgt der Inline-Einrichtung Muster. Die zweite Version folgt Methode der Erstellung y Delegierte Einrichtung Muster.

Im Allgemeinen bin ich gegen Kommentare, es sei denn, sie erklären das "Warum" des Codes. Das Lesen von Onkel Bob Martins Sauberer Code hat mich davon überzeugt. Es gibt ein Kapitel über Kommentare, und es gibt ein Kapitel über Tests. Ich empfehle es.

Weitere Informationen über bewährte Verfahren für automatisierte Tests finden Sie unter xUnit-Muster .

4voto

Bill the Lizard Punkte 384619

Der Name der Prüfmethode sollte genau beschreiben, was Sie prüfen. Aus der Dokumentation sollte hervorgehen, warum der Test fehlschlägt.

0voto

Chris Lacasse Punkte 1342

Sie sollten eine Kombination aus beschreibenden Methodennamen und Kommentaren im Doc-String verwenden. Eine gute Möglichkeit ist die Aufnahme einer grundlegenden Prozedur und von Überprüfungsschritten in den Dokumentationsstring. Wenn Sie diese Tests dann mit einem Test-Framework ausführen, das die Ausführung der Tests und die Erfassung der Ergebnisse automatisiert, können Sie das Framework veranlassen, den Inhalt des Doc-Strings für jede Testmethode zusammen mit stdout+stderr zu protokollieren.

Hier ist ein einfaches Beispiel:

class SimpelTestCase(unittest.TestCase):
    def testSomething(self):
        """ Procedure:
            1. Print something
            2. Print something else
            ---------
            Verification:
            3. Verify no errors occurred
        """
        print "something"
        print "something else"

Wenn Sie das Verfahren zusammen mit dem Test haben, ist es viel einfacher herauszufinden, was der Test macht. Und wenn Sie den Docstring mit der Testausgabe einschließen, ist es viel einfacher herauszufinden, was falsch gelaufen ist, wenn Sie später die Ergebnisse durchgehen. Die Firma, bei der ich früher gearbeitet habe, hat so etwas gemacht, und es hat sehr gut funktioniert, wenn es zu Fehlern kam. Wir haben die Unit-Tests bei jedem Checkin automatisch mit CruiseControl ausgeführt.

0voto

Tim Ottinger Punkte 1412

Wenn der Test fehlschlägt (was der Fall sein sollte, bevor er überhaupt besteht), sollten Sie die Fehlermeldung sehen und wissen, was los ist. Das passiert nur, wenn Sie es so planen.

Es geht ausschließlich um die Benennung der Testklasse, der Testmethode und der Assert-Meldung. Wenn ein Test fehlschlägt und Sie anhand dieser drei Hinweise nicht erkennen können, was los ist, sollten Sie einige Dinge umbenennen oder einige Testklassen auflösen.

Es passiert nicht, wenn der Name der Fixture ClassXTests und der Name des Tests TestMethodX lautet und die Fehlermeldung "expected true, returned false" lautet. Das ist ein Zeichen für schlampig geschriebene Tests.

In den meisten Fällen sollten Sie weder den Test noch Kommentare lesen müssen, um zu wissen, was passiert ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X