Ausführen eines bestimmten Testfalls in Django, wenn Ihre App über ein Testverzeichnis verfügt


163

In der Django-Dokumentation ( http://docs.djangoproject.com/de/1.3/topics/testing/#running-tests ) heißt es, dass Sie einzelne Testfälle ausführen können, indem Sie sie angeben:

$ ./manage.py test animals.AnimalTestCase

Dies setzt voraus, dass Sie Ihre Tests in einer tests.py-Datei in Ihrer Django-Anwendung haben. Wenn dies zutrifft, funktioniert dieser Befehl wie erwartet.

Ich habe meine Tests für eine Django-Anwendung in einem Testverzeichnis:

my_project/apps/my_app/
├── __init__.py
├── tests
   ├── __init__.py
   ├── field_tests.py
   ├── storage_tests.py
├── urls.py
├── utils.py
└── views.py

Die tests/__init__.pyDatei hat eine suite () Funktion:

import unittest

from my_project.apps.my_app.tests import field_tests, storage_tests

def suite():
    tests_loader = unittest.TestLoader().loadTestsFromModule
    test_suites = []
    test_suites.append(tests_loader(field_tests))
    test_suites.append(tests_loader(storage_tests))
    return unittest.TestSuite(test_suites)

Um die Tests durchzuführen, mache ich:

$ ./manage.py test my_app

Der Versuch, einen einzelnen Testfall anzugeben, löst eine Ausnahme aus:

$ ./manage.py test my_app.tests.storage_tests.StorageTestCase
...
ValueError: Test label 'my_app.tests.storage_tests.StorageTestCase' should be of the form app.TestCase or app.TestCase.test_method

Ich habe versucht, das zu tun, was in der Ausnahmemeldung stand:

$ ./manage.py test my_app.StorageTestCase
...
ValueError: Test label 'my_app.StorageTestCase' does not refer to a test

Wie spezifiziere ich einen einzelnen Testfall, wenn sich meine Tests in mehreren Dateien befinden?

Antworten:


155

Kasse Django-Nase . Hier können Sie Tests angeben, die wie folgt ausgeführt werden sollen:

python manage.py test another.test:TestCase.test_method

oder verwenden Sie, wie in den Kommentaren angegeben, die folgende Syntax:

python manage.py test another.test.TestCase.test_method

Danke @sdolan. Stieß auf das gleiche Problem wie Hekevintran. Auf Django-Nase umgestellt und dieses Problem behoben, funktioniert es auch viel besser als der Standard-Django-Testläufer.
LeeMobile

Dadurch wird ein Test ausgeführt, aber wie wird ein gesamter TestCase ausgeführt?
jMyles

5
@jMyles:another.test:TestCase
Sam Dolan

4
Achtung Leute wie ich, die blind aus Stackoverflow einfügen: Dies wird ohne das erwähnte Plugin fehlerhaft sein. Verwenden Sie die in der anderen Antwort beschriebene Syntax (. Anstelle von :), die in Django 1.6+ funktioniert.
Andy Smith

1
Ich habe diese Antwort abgelehnt, weil sie die Frage des OP, wie man das in Django macht, eigentlich nicht beantwortet. Vielmehr schlägt es nur vor, zu Nosetest zu wechseln
Josh Brown

175

Seit Django 1.6 können Sie einen vollständigen Testfall oder einen einzelnen Test mit der vollständigen Punktnotation für das Element ausführen, das Sie ausführen möchten.

Die automatische Testerkennung findet jetzt Tests in jeder Datei, die mit dem Test beginnt, im Arbeitsverzeichnis. Wenn Sie also die Frage beantworten, die Sie zum Umbenennen Ihrer Dateien benötigen, können Sie sie jetzt im gewünschten Verzeichnis behalten. Wenn Sie benutzerdefinierte Dateinamen verwenden möchten, können Sie ein Muster (Standard-Django-Testläufer) mit dem Optionsflag angeben --pattern="my_pattern_*.py".

Wenn Sie sich also in Ihrem manage.pyVerzeichnis befinden und den Test test_ainnerhalb der TestCaseUnterklasse Ain einer Datei tests.pyunter der App / dem Modul ausführen möchten, examplewürden Sie Folgendes tun:

python manage.py test example.tests.A.test_a

Wenn Sie keine Abhängigkeit einfügen möchten und sich in Django 1.6 oder höher befinden, gehen Sie so vor.

Weitere Informationen finden Sie in der Django-Dokumentation


Schön zu sehen, dass diese Funktion jetzt in Django integriert ist.
Hekevintran

Ich kann das überhaupt nicht zum error: option --pattern not recognizedinvalid command name
Laufen bringen

Dies funktioniert hervorragend in Django v3!
Kirk

11

Ich hatte dieses Problem selbst und fand diese Frage, falls jemand anderes mitkommt, hier ist, was ich ausgegraben habe. Der DjangoTestSuiteRuner verwendet eine Methode namens build_test (label), die anhand des Labels herausfindet, welche Testfälle ausgeführt werden sollen. Wenn man sich diese Methode ansieht, stellt sich heraus, dass sie ein getattr () für das Modul "models" oder "test" ausführen. Wenn Sie also eine Suite zurückgeben, sucht der Testläufer nicht nach Ihren Testfällen in dieser Suite, sondern nur in einem dieser Module.

Eine schnelle Lösung besteht darin __init__.py, Ihre Tests direkt zu importieren, anstatt eine Suite zu definieren. Das macht sie Teil des "Test" -Moduls und so kann build_test (label) sie finden.

Für Ihr Beispiel oben tests/__init__.pysollte einfach enthalten:

from field_tests import *
from storage_tests import *

Dies ist nicht sehr elegant und natürlich funktioniert dies nicht, wenn Sie versuchen, etwas Komplizierteres mit Ihrer Suite zu tun, aber in diesem Fall.




3

Fügen Sie diesen Code in Ihre __init__.py ein und es werden alle Testklassen in das Paket und die Unterpakete importiert. Auf diese Weise können Sie bestimmte Tests ausführen, ohne jede Datei manuell zu importieren.

import pkgutil
import unittest

for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(module_name).load_module(module_name)
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
            exec ('%s = obj' % obj.__name__)

Ebenso können Sie für Ihre Testsuite einfach Folgendes verwenden:

def suite():   
    return unittest.TestLoader().discover("appname.tests", pattern="*.py")

Jetzt müssen Sie für neue Tests nur noch schreiben und sicherstellen, dass sie sich im Testordner befinden. Keine langwierige Wartung der Importe mehr!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.