Gibt es einen Wert beim Schreiben eines Komponententests, der eine Teilmenge eines anderen Tests ist?

15

Nehmen wir an, ich möchte testen, ob eine Funktion zwei Zahlen zurückgibt und die erste kleiner ist als die zweite:

def test_length():
    result = my_function()
    assert len(result) == 2

def test_order()
    a, b = my_function()
    assert a < b

Wenn dies test_lengthfehlschlägt, test_orderwird dies auch fehlschlagen. Ist es eine bewährte Methode, zu schreiben test_lengthoder zu überspringen?

BEARBEITEN: Beachten Sie, dass in dieser Situation beide Tests größtenteils unabhängig voneinander sind, jeder einzeln ausgeführt werden kann oder in umgekehrter Reihenfolge ausgeführt werden kann, dies spielt keine Rolle. Also keine dieser früheren Fragen

ist ein Duplikat des obigen.

Mihai
quelle
2
@ GlenH7 - das scheint eine andere Frage zu sein. Die andere lautet "Wenn Sie Funktionen haben, bei denen AAufrufe Bund das gleiche Ergebnis zurückgeben, sollten Sie beide Aund testen B". Hier geht es eher um die Überlappung der Tests als um die zu testenden Funktionen. (Obwohl es verwirrend ist, wie sie derzeit benannt sind).
Telastyn,
1
Genau genommen überlappen sich diese Tests nicht wirklich (sie haben keine Erfolgsabhängigkeit). Eine Funktion lambda: type('', (), {'__len__': lambda self: 2})()übergibt die erste, aber nicht die zweite.
Liori
1
@ GlenH7: FWIW, ich habe die Frage nicht wirklich geändert, habe nur versucht, sie gnat-safe zu machen ;-) (@gnat: keine Beleidigung, nur ein Scherz!)
Doc Brown

Antworten:

28

Es kann einen Wert geben, aber das ist ein bisschen ein Geruch. Entweder sind Ihre Tests nicht gut isoliert (da test_orderwirklich zwei Dinge getestet werden) oder Sie sind zu dogmatisch in Ihren Tests (zwei Tests testen das gleiche logische Ding).

Im Beispiel würde ich die beiden Tests zusammenführen. Ja, es bedeutet, dass Sie mehrere Asserts haben. Schade. Sie testen immer noch eine einzige Sache - das Ergebnis der Funktion. In der realen Welt bedeutet das manchmal, zwei Prüfungen durchzuführen.

Telastyn
quelle
Ich habe Ihre Antwort positiv bewertet, obwohl sie einen kleinen Punkt verfehlt. In Python my_functionschlägt der zweite Test ebenfalls fehl, wenn nicht genau zwei Werte ohne Assert zurückgegeben werden - da die Zuweisung zu einer Ausnahme führt. Es ist also nicht erforderlich, mehrere Asserts und zwei Prüfungen zu verwenden, um dasselbe zu testen.
Doc Brown
@DocBrown - Ich habe das angenommen, aber ich kenne die Fehlermeldungen von Python nicht, um zu wissen, ob es aus informativen Gründen sinnvoll ist, einen Assert-Fehler anstelle einer zufälligen Ausnahme / eines zufälligen Fehlers zu haben.
Telastyn,
Ich denke in der aktuellen Situation wäre die Fehlermeldung wahrscheinlich informativ genug. Im Allgemeinen ist dies jedoch möglicherweise nicht der Fall. Deshalb stimme ich Ihnen zu, dass der allgemeine Ansatz für einen Fall wie diesen darin bestehen sollte, an eine "Zusammenführung" zu denken, bei der zwei Aussagen verwendet werden. Wenn sich herausstellt, dass der Test weiter vereinfacht werden kann, indem eine der Aussagen weggelassen wird, ist das in Ordnung.
Doc Brown
5
@DocBrown Der andere Wert bei der expliziten Überprüfung mit einer Zusicherung ist, dass jedem, der den Test untersucht, klar wird, dass dies ein Fehler des zu testenden Codes ist und nicht der Test selbst. Wenn meine Tests auf unerwartete Ausnahmen stoßen, muss ich immer einige Zeit darauf verwenden, herauszufinden, welche tatsächlich falsch ist.
Chris Hayes
@ ChrisHayes: Ich schrieb "Es gibt keine Notwendigkeit", nicht "Es gibt keinen Wert" darin.
Doc Brown
5

Ihre Tests sollten explizit sein. Es lässt sich nicht vollständig ableiten, dass test_order fehlschlägt, wenn text_length fehlschlägt.

Ich bin mir nicht sicher, wie es in Python len(result)läuft, das du gepostet hast, aber wenn 3 ist, wird das erste scheitern, aber das zweite wird vergehen (und wenn nicht in Python, dann sicher in Sprachen wie JavaScript).

Wie Sie bereits sagten, möchten Sie testen, ob die Funktion zwei Zahlen zurückgibt und ob diese in Ordnung sind. Es sind zwei Tests.

Madara Uchiha
quelle
1
It's not completely inferred that if text_length fails test_order fails- In Python gibt es eine Ausnahme.
Doc Brown
Ich denke, die Frage bezieht sich auf den Fall, in dem das Scheitern von das Scheitern von test_lengthimpliziert test_order. Die Tatsache, dass sich ein ähnliches Testpaar, das in Javascript geschrieben wurde, nicht so verhält wie diese beiden Python-Tests, ist irrelevant.
Laut Dawood wird Monica am
2
@DavidWallace: Denken Sie daran, die Frage lautete "Ist es eine bewährte Methode, test_length zu schreiben oder zu überspringen"? In Javascript benötigen Sie beide Tests, um sicherzustellen, dass Sie kein Problem übersehen haben (wenn Sie die beiden Tests nicht zu einem zusammenführen). In Python können Sie das erste ohne Bedenken weglassen (was im ersten Satz dieser Antwort abgelehnt und im zweiten als "Ich bin nicht sicher" deklariert wird). Ehrlich gesagt sieht eine gute Antwort anders aus. Ich habe diese Antwort jedoch nicht abgelehnt, da der gute Teil eigentlich die Erwähnung von JavaScript ist.
Doc Brown
4
@DavidWallace: Da wir hier ein Programmierer sind, nicht auf stackoverflow.com, ist es meiner Meinung nach besser, eine Antwort zu geben, die auf mehr als eine Sprache angewendet werden kann, als eine Antwort nur für eine bestimmte Sprache. Wenn Sie sich jedoch auf eine bestimmte Sprache beziehen, sollte die Antwort in Bezug auf die Sprache korrekt sein und einige Eigenschaften nicht verwechseln.
Doc Brown
1
Die Frage lautet: "Lohnt es sich, einen Test zu schreiben, der eine Teilmenge eines anderen Tests ist?" In dieser Antwort heißt es: "In einigen Sprachen ist keiner Ihrer Tests eine Teilmenge des anderen." deshalb notwendig. Es liest sich für mich so, als ob jemand sagte: "Ihr Code wird in C ++ überhaupt nicht kompiliert, und außerdem kann eine Funktion in C ++ nur einen Wert zurückgeben, sodass Sie nicht testen müssen. Es werden zwei zurückgegeben. Schreiben Sie nur einen Test." ;-)
Steve Jessop
2

Der einzige Wert von test_lengthhier ist, dass, wenn alles bestanden ist, das Vorhandensein anzeigt, dass "Länge" getestet wurde.

Es ist also wirklich unnötig, beide Tests durchzuführen. Nur beibehalten, test_orderaber eventuell umbenennen test_length_and_order.

Übrigens finde ich die Verwendung von Namen, die testetwas ungeschickt beginnen. Ich bin ein starker Verfechter von Testnamen, die den von Ihnen behaupteten Zustand beschreiben.

Laut Dawood soll Monica wieder eingesetzt werden
quelle
1
Die testWarze ist für Pythons Test-Framework von Bedeutung. Was sich natürlich nicht ändern muss, ob Sie ein Fan davon sind, aber es ändert sich das Gewicht der Argumente, die erforderlich sind, um jemanden davon abzuhalten, es zu benutzen ;-)
Steve Jessop
@SteveJessop Ja, ich vergesse immer wieder, dass es gebraucht wird. Als ich vor einiger Zeit Python-Tests geschrieben habe, habe ich mir angewöhnt, sie alle mit test_that_, wie test_that_return_values_are_in_orderund so weiter zu beginnen. Vielleicht wird eine zukünftige Version des Test-Frameworks diese Anforderung irgendwie umgehen.
Dawood sagt, Monica am
@DavidWallace: Sie können das Präfix ändern, wenn Sie möchten.
Lie Ryan
1

Ich würde diese Tests getrennt lassen, wenn sie sich so entwickelt haben. Ja test_orderwird wahrscheinlich immer scheitern test_length, aber Sie wissen definitiv warum.

Ich würde auch zustimmen, dass, wenn das test_orderzuerst erschien und Sie einen testbaren Fehler fanden, das Ergebnis möglicherweise nicht zwei Werte waren, diese Prüfung als hinzufügen assertund den Test umbenennen, um test_length_and_orderSinn zu machen.

Wenn Sie auch überprüfen müssten, ob es sich bei den zurückgegebenen Werten um Ganzzahlen handelt, würde ich dies in diesen "Omnibus" -Ergebnis-Test einbeziehen.

Beachten Sie jedoch, dass Sie jetzt eine Reihe von Tests für das Ergebnis von haben my_function(). Wenn mehrere Kontexte (oder wahrscheinlicher mehrere Parameter) zu testen sind, kann dies jetzt eine Unterroutine sein, mit der alle Ergebnisse getestet werden können my_function().

Wenn ich Unit-Tests schreibe, teste ich normalerweise die Edge- und Bad-Cases getrennt von der guten Eingabe und der normalen Ausgabe (teilweise, weil die meisten meiner "Unit" -Tests häufig Mini-Integrationstests sind) und häufig mit mehreren Asserts, die nur fehlerhaft sind in separate Tests, wenn sie in einer Weise fehlschlagen, in der ich finde, dass ich mehr Informationen möchte, ohne Fehler zu beheben.

Also habe ich wahrscheinlich mit Ihrem separaten Tests und erweitern beginnen würde test_lengthzu test_length_and_typesund verlassen zu test_ordertrennen, wird die letztere Annahme gesehen „normale Verarbeitung“ zu sein.

Mark Hurd
quelle