Testen von Funktionen, die in Python iterierbar sind

8

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.

%Vor%

Dies wird nicht funktionieren, da perm3() ein iterables ist, nicht ein Liste. So können wir dieses spezielle Beispiel beheben.

%Vor%

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.

    
Tarrasch 28.09.2012, 16:21
quelle

4 Antworten

4

Ich benutze KennyTMs assertRecursiveEq :

%Vor%     
unutbu 28.09.2012, 17:13
quelle
2

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%     
dbn 04.10.2012 20:41
quelle
1

Sie könnten Ihren Vorschlag erweitern, um type einzuschließen (das erlaubte Ihnen, zwischen Listen, Tupeln usw. zu unterscheiden), so:

%Vor%

Zum Beispiel:

%Vor%

.

Zu erwähnen ist, dass type bei der Unterscheidung zwischen Objekten grob ist. <type 'classobj'> ...

    
Andy Hayden 28.09.2012 17:02
quelle
0

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.

%Vor%

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!

    
Tarrasch 28.09.2012 16:21
quelle

Tags und Links