Ich habe Schwierigkeiten beim Testen von Python-Funktionen
Rückgabe eines iterablen, wie Funktionen, die sind
Nachgeben oder Funktionen, die einfach einen iterierbaren Wert wie return imap(f, some_iter)
oder return permutations([1,2,3])
zurückgeben.
Bei dem Beispiel der Permutationen erwarte ich, dass die Ausgabe der Funktion [(1, 2, 3), (1, 3, 2), ...]
ist. Also fange ich an, meinen Code zu testen.
Dies wird nicht funktionieren, da perm3()
ein iterables ist, nicht ein
Liste. So können wir dieses spezielle Beispiel beheben.
Und das funktioniert gut. Aber was, wenn ich iterable verschachtelt habe? Das ist
Iterables ergeben Iterables? Wie sagen die Ausdrücke
%Code%. Das ist es jetzt
wahrscheinlich nicht nützlich, aber es ist klar, dass es sein wird (einmal entrollt die
Iteratoren) etwas wie product(permutations([1, 2]), permutations([3, 4]))
.
Allerdings können wir nicht nur [((1, 2), (3, 4)), ((1, 2), (4, 3)), ...]
um unser Ergebnis wickeln, da dies nur der Fall ist
Wende list
auf iterable<blah>
. Gut
Natürlich kann ich [iterable<blah>, iterable<blah>, ...]
machen, aber das funktioniert nur für eine
Verschachtelungsebene von 2.
Also, hat die Python-Test-Community irgendeine Lösung für die Probleme beim Testen von Iterablen? Natürlich können einige iterables nicht auf diese Weise getestet werden, wie wenn du einen unendlichen Generator willst, aber Trotzdem sollte dieses Thema so weit verbreitet sein, dass jemand darüber nachdenken kann darüber.
1. Wenn die Reihenfolge der Ergebnisse keine Rolle spielt
Verwenden Sie unittest.assertItemsEqual () . Dies testet, dass die Elemente sowohl in Selbst- als auch in Referenz vorhanden sind, ignoriert jedoch die Reihenfolge. Dies funktioniert in Ihrem Beispiel für ein verschachteltes Beispiel. Es funktioniert auch auf einem 2-tiefen Beispiel, das ich zusammengebraut habe.
2. Wenn die Reihenfolge der Ergebnisse wichtig ist
Ich würde vorschlagen, die Ergebnisse von perm3 () nie auf eine Liste zu übertragen. Vergleichen Sie stattdessen die Elemente direkt beim Iterieren. Hier ist eine Testfunktion, die für Ihr Beispiel funktioniert. Ich habe es einer Unterklasse von unittest.TestCase hinzugefügt:
%Vor%Benutze es wie:
%Vor% Sie könnten Ihren Vorschlag erweitern, um type
einzuschließen (das erlaubte Ihnen, zwischen Listen, Tupeln usw. zu unterscheiden), so:
Zum Beispiel:
%Vor%.
Zu erwähnen ist, dass type
bei der Unterscheidung zwischen Objekten grob ist. <type 'classobj'>
...
Ich kenne keine Standardmethode, mit der Python-Programmierer iterierbare Tests durchführen, aber Sie
kann einfach Ihre Idee von map
und list
auf eine rekursive Funktion anwenden
Arbeiten für jede Ebene der Verschachtelung.
Dann wird dein Test tatsächlich funktionieren.
%Vor%Allerdings gibt es einen Fehler damit, wie Sie sehen können. Wenn man etwas abrollt, dann wird immer zu einem Array gedreht werden, das war wünschenswert für iterables aber es gilt auch für die Tupel. Also musste ich die Tupel im erwarteten Ergebnis manuell in Listen umwandeln. Daher können Sie nicht differentiieren, wenn Ausgaben Listen oder Tupel sind.
Ein weiteres Problem bei diesem naiven Ansatz ist, dass ein bestandener Test nicht bedeutet
dass die Funktion funktioniert. Angenommen, Sie überprüfen assertEqual(list(my_fun()), [1, 2,
3])
, während Sie glauben, dass es iterierbar ist, wenn "aufgelistet" ist
gleich [1, 2, 3]
. Es könnte sein, dass es kein iterables wie Sie zurückgegeben hat
gewollt hätte es vielleicht auch eine Liste oder ein Tupel zurückgegeben!