Ich habe eine Art Testdaten und möchte für jeden Artikel einen Komponententest erstellen. Meine erste Idee war es so zu machen:
import unittest
l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]
class TestSequence(unittest.TestCase):
def testsample(self):
for name, a,b in l:
print "test", name
self.assertEqual(a,b)
if __name__ == '__main__':
unittest.main()
Der Nachteil dabei ist, dass alle Daten in einem Test verarbeitet werden. Ich möchte einen Test für jeden Artikel im laufenden Betrieb erstellen. Irgendwelche Vorschläge?
python
unit-testing
parameterized-unit-test
Peter Hoffmann
quelle
quelle
Antworten:
Dies wird als "Parametrisierung" bezeichnet.
Es gibt verschiedene Tools, die diesen Ansatz unterstützen. Z.B:
Der resultierende Code sieht folgendermaßen aus:
Welches wird die Tests generieren:
Aus historischen Gründen werde ich die ursprüngliche Antwort um 2008 belassen):
Ich benutze so etwas:
quelle
.__name__ =
um das.exact_method
Testen zu aktivierenif __name__ == '__main__'
Bedingung angezeigt? Sicherlich sollte es darüberVerwenden von unittest (seit 3.4)
Seit Python 3.4 verfügt das Standardbibliothekspaket
unittest
über densubTest
Kontextmanager.Siehe die Dokumentation:
Beispiel:
Sie können auch eine benutzerdefinierte Nachricht und Parameterwerte angeben, um
subTest()
:Mit der Nase
Die Nase - Test - Framework unterstützt dies .
Beispiel (der folgende Code ist der gesamte Inhalt der Datei, die den Test enthält):
Die Ausgabe des Befehls nosetests:
quelle
Dies kann elegant mit Metaclasses gelöst werden:
quelle
__new__
Methode in der Metaklasse wird aufgerufen, wenn die Klasse selbst definiert wird, nicht wenn die erste Instanz erstellt wird. Ich würde mir vorstellen, dass diese Methode zum dynamischen Erstellen von Testmethoden besser mit der Selbstbeobachtung kompatibel ist, mit derunittest
bestimmt wird, wie viele Tests sich in einer Klasse befinden (dh sie kann die Liste der Tests zusammenstellen, bevor jemals eine Instanz dieser Klasse erstellt wird).class TestSequence(unittest.TestCase, metaclass=TestSequenceMeta):[...]
dct
anstelle von verwendendict
? Die Verwendung von Schlüsselwörtern als Variablennamen ist verwirrend und fehleranfällig.Ab Python 3.4 wurden zu diesem Zweck Untertests für unittest eingeführt. Einzelheiten finden Sie in der Dokumentation . TestCase.subTest ist ein Kontextmanager, mit dem Asserts in einem Test isoliert werden können, sodass ein Fehler mit Parameterinformationen gemeldet wird, die Testausführung jedoch nicht gestoppt wird. Hier ist das Beispiel aus der Dokumentation:
Die Ausgabe eines Testlaufs wäre:
Dies ist auch Teil von unittest2 , sodass es für frühere Versionen von Python verfügbar ist.
quelle
setUp()
undtearDown()
werden nicht zwischen den Untertests ausgeführt.)self.setUp()
kann aber theoretisch manuell aus dem Subtest heraus aufgerufen werden. WastearDown
automatisch am Ende könnte ausreichen, nannte es zu haben.load_tests ist ein wenig bekannter Mechanismus, der in 2.7 eingeführt wurde, um eine TestSuite dynamisch zu erstellen. Mit ihm können Sie einfach parametrisierte Tests erstellen.
Beispielsweise:
Dieser Code führt alle Testfälle in der TestSuite aus, die von load_tests zurückgegeben werden. Der Erkennungsmechanismus führt keine anderen Tests automatisch aus.
Alternativ können Sie auch die Vererbung verwenden, wie in diesem Ticket gezeigt: http://bugs.python.org/msg151444
quelle
Dies kann mit pytest erfolgen . Schreiben Sie einfach die Datei
test_me.py
mit Inhalt:Und führen Sie Ihren Test mit Befehl aus
py.test --tb=short test_me.py
. Dann sieht die Ausgabe folgendermaßen aus:Es ist einfach!. Auch pytest hat mehr Funktionen wie
fixtures
,mark
,assert
, etc ...quelle
py.test
unittest
py.test zu wechseln. Früher hatte ichTestCase
Basisklassen, die in der Lage waren, Kinder mit verschiedenen Argumenten dynamisch zu erstellen, die sie als Klassenvariablen speichern würden ... was etwas unhandlich war.py.test
ist Yield_Fixtures . Was das Setup tun kann , einige nützliche Daten in den Test zurückgeben und nach Testende den Abriss durchführen . Vorrichtungen können auch parametirisiert werden .Verwenden Sie die ddt- Bibliothek. Es werden einfache Dekoratoren für die Testmethoden hinzugefügt:
Diese Bibliothek kann mit installiert werden
pip
. Es ist nicht erforderlichnose
und funktioniert hervorragend mit dem Standardbibliotheksmodulunittest
.quelle
Sie würden von der TestScenarios- Bibliothek profitieren .
quelle
Es gibt auch eine Hypothese, die Fuzz- oder eigenschaftsbasierte Tests hinzufügt: https://pypi.python.org/pypi/hypothesis
Dies ist eine sehr leistungsfähige Testmethode.
quelle
@given()
Makro in der unittest-Klasse verwenden.Sie können das Nose-Ittr- Plugin (
pip install nose-ittr
) verwenden.Die Integration in vorhandene Tests ist sehr einfach. Es sind nur minimale Änderungen (falls vorhanden) erforderlich. Es unterstützt auch das Nasen- Multiprocessing-Plugin.
Nicht, dass Sie auch eine Anpassungsfunktion
setup
pro Test haben können.Es ist auch möglich,
nosetest
Parameter wie mit ihrem eingebauten Plugin zu übergebenattrib
. Auf diese Weise können Sie nur einen bestimmten Test mit bestimmten Parametern ausführen:quelle
Ich benutze Metaklassen und Dekorateure, um Tests zu generieren. Sie können meine Implementierung python_wrap_cases überprüfen . Diese Bibliothek benötigt keine Test-Frameworks.
Ihr Beispiel:
Konsolenausgabe:
Sie können auch Generatoren verwenden . Beispielsweise generiert dieser Code alle möglichen Kombinationen von Tests mit Argumenten
a__list
undb__list
Konsolenausgabe:
quelle
Ich bin neulich auf ParamUnittest gestoßen, als ich mir den Quellcode für Radon angesehen habe ( Beispiel für die Verwendung im Github-Repo ). Es sollte mit anderen Frameworks funktionieren, die TestCase erweitern (wie Nose).
Hier ist ein Beispiel:
quelle
ERGEBNIS:
quelle
def add_test_methods
Funktion. Solltedef _add_test_methods
ich denkenVerwenden Sie einfach Metaklassen, wie hier gezeigt;
Ausgabe:
quelle
Sie können
TestSuite
benutzerdefinierteTestCase
Klassen verwenden.quelle
__init__
function weitergegeben.Ich habe festgestellt, dass dies für meine Zwecke gut funktioniert, insbesondere wenn ich Tests generieren muss, die geringfügig unterschiedliche Prozesse für eine Datensammlung ausführen.
Die
TestGenerator
Klasse kann verwendet werden, um verschiedene Sätze von Testfällen wie zu erzeugenTestCluster
.TestCluster
kann als Implementierung derTestGenerator
Schnittstelle betrachtet werden.quelle
Diese Lösung funktioniert mit
unittest
undnose
für Python 2 und Python 3:quelle
Ich hatte Probleme mit einem ganz bestimmten Stil parametrisierter Tests. Alle unsere Selenium-Tests können lokal ausgeführt werden, sie sollten jedoch auch remote auf mehreren Plattformen in SauceLabs ausgeführt werden können. Grundsätzlich wollte ich eine große Anzahl bereits geschriebener Testfälle mit möglichst wenigen Codeänderungen parametrisieren. Außerdem musste ich in der Lage sein, die Parameter an die setUp-Methode zu übergeben, für die ich anderswo keine Lösungen gesehen habe.
Folgendes habe ich mir ausgedacht:
Alles, was ich tun musste, war, jedem normalen alten TestCase einen einfachen Dekorator @sauce_labs () hinzuzufügen, und jetzt, wenn sie ausgeführt werden, werden sie verpackt und neu geschrieben, sodass alle Testmethoden parametrisiert und umbenannt werden. LoginTests.test_login (self) wird ausgeführt als LoginTests.test_login_internet_explorer_10.0 (self), LoginTests.test_login_internet_explorer_11.0 (self) und LoginTests.test_login_firefox_43.0 (self), und jeder hat den Parameter self.platform zu entscheiden Plattform, auf der auch in LoginTests.setUp ausgeführt werden kann, was für meine Aufgabe von entscheidender Bedeutung ist, da dort die Verbindung zu SauceLabs initialisiert wird.
Wie auch immer, ich hoffe, dies könnte jemandem helfen, der eine ähnliche "globale" Parametrisierung seiner Tests durchführen möchte!
quelle
Die metaklassenbasierten Antworten funktionieren weiterhin in Python3, aber anstelle des
__metaclass__
Attributs muss dermetaclass
Parameter wie folgt verwendet werden:quelle
Meta-Programmierung macht Spaß, kann aber auf dem Weg sein. Die meisten Lösungen hier machen es schwierig:
Mein erster Vorschlag ist also, dem einfachen / expliziten Pfad zu folgen (funktioniert mit jedem Testläufer):
Da wir uns nicht wiederholen sollten, baut mein zweiter Vorschlag auf der Antwort von @ Javier auf: Umfassen Sie eigenschaftsbasierte Tests. Hypothesenbibliothek:
hat viele weitere interessante Funktionen (Statistiken, zusätzliche Testausgabe, ...)
Klasse TestSequence (unittest.TestCase):
Um Ihre spezifischen Beispiele zu testen, fügen Sie einfach hinzu:
Um nur ein bestimmtes Beispiel auszuführen, können Sie die anderen Beispiele auskommentieren (vorausgesetzt, das Beispiel wird zuerst ausgeführt). Möglicherweise möchten Sie verwenden
@given(st.nothing())
. Eine andere Möglichkeit besteht darin, den gesamten Block durch Folgendes zu ersetzen:Ok, Sie haben keine eindeutigen Testnamen. Aber vielleicht brauchen Sie nur:
Lustigeres Beispiel
quelle
Super spät zur Party, aber ich hatte Probleme damit, dass diese funktionieren
setUpClass
.Hier ist eine Version von @ Javiers Antwort , die den
setUpClass
Zugriff auf dynamisch zugewiesene Attribute ermöglicht.Ausgänge
quelle
Nur um eine andere Lösung in die Mischung zu werfen;)
Dies ist praktisch das gleiche wie
parameterized
oben erwähnt, jedoch spezifisch fürunittest
:Anwendungsbeispiel:
quelle
Neben setattr können wir seit Python 3.2 load_tests verwenden. Bitte lesen Sie den Blog-Beitrag blog.livreuro.com/de/coding/python/how-to-generate-discoverable-unit-tests-in-python-dynamically/
quelle
Das Folgende ist meine Lösung. Ich finde dies nützlich, wenn: 1. für unittest funktionieren sollte. Testfall und unittest entdecken 2. Eine Reihe von Tests für verschiedene Parametereinstellungen ausführen lassen. 3. Sehr einfach, keine Abhängigkeit von anderen Paketen importieren unittest
quelle
quelle