1018 Stimmen

Ausführung von unittest mit typischer Testverzeichnisstruktur

Die übliche Verzeichnisstruktur selbst für ein einfaches Python-Modul scheint darin zu bestehen, die Unit-Tests in ihre eigenen test Verzeichnis:

new_project/
    antigravity/
        antigravity.py
    test/
        test_antigravity.py
    setup.py
    etc.

siehe zum Beispiel dies Anleitung zum Python-Projekt .

Meine Frage ist einfach Wie werden die Tests in der Regel durchgeführt? Ich vermute, das ist für alle außer mir offensichtlich, aber man kann nicht einfach python test_antigravity.py aus dem Testverzeichnis als seine import antigravity wird fehlschlagen, da das Modul nicht im Pfad enthalten ist.

Ich weiß, dass ich PYTHONPATH und andere Suchpfad-bezogene Tricks ändern könnte, aber ich kann nicht glauben, dass das der einfachste Weg ist - es ist in Ordnung, wenn Sie der Entwickler sind, aber nicht realistisch zu erwarten, dass Ihre Benutzer es benutzen, wenn sie nur überprüfen wollen, ob die Tests erfolgreich sind.

Die andere Alternative ist, die Testdatei einfach in das andere Verzeichnis zu kopieren, aber das scheint etwas dumm und verfehlt den Sinn, sie zunächst in einem separaten Verzeichnis zu haben.

Wenn Sie also gerade den Quellcode meines neuen Projekts heruntergeladen hätten, wie würden Sie die Unit-Tests ausführen? Ich würde eine Antwort bevorzugen, die es mir ermöglicht, meinen Benutzern zu sagen: "Um die Unit-Tests auszuführen, machen Sie X."

6 Stimmen

@EMP Die richtige Lösung, wenn Sie den Suchpfad festlegen müssen, ist,... den Suchpfad festzulegen. Welche Art von Lösung haben Sie erwartet?

9 Stimmen

@CarlMeyer eine andere bessere Lösung ist die Verwendung der unittest Befehlszeilenschnittstelle wie in meinem Antwort unten damit Sie das Verzeichnis nicht zum Pfad hinzufügen müssen.

65 Stimmen

Das gilt auch für mich. Ich habe gerade damit begonnen, meine allerersten Unit-Tests für ein kleines Python-Projekt zu schreiben und habe mehrere Tage gebraucht, um mich mit der Tatsache auseinanderzusetzen, dass ich nicht ohne weiteres einen Test ausführen kann, während ich meine Quellen in einem src-Verzeichnis und die Tests in einem Test-Verzeichnis aufbewahre, anscheinend mit einem der vorhandenen Test-Frameworks. Ich werde schließlich Dinge akzeptieren, einen Weg finden; aber dies war eine sehr frustrierende Einführung. (Und ich bin ein Unit-Testing-Veteran außerhalb von Python.)

930voto

Pierre Punkte 11480

Die beste Lösung ist meiner Meinung nach die Verwendung der unittest Befehlszeilenschnittstelle was das Verzeichnis in die Datei sys.path damit Sie das nicht tun müssen (im TestLoader Klasse).

Zum Beispiel für eine Verzeichnisstruktur wie diese:

new_project
 antigravity.py
 test_antigravity.py

Sie können einfach weglaufen:

$ cd new_project
$ python -m unittest test_antigravity

Für eine Verzeichnisstruktur wie die Ihre:

new_project
 antigravity
    __init__.py         # make it a package
    antigravity.py
 test
     __init__.py         # also make test a package
     test_antigravity.py

Und in den Testmodulen innerhalb der test Paket, können Sie die antigravity Paket und seine Module wie gewohnt:

# import the package
import antigravity

# import the antigravity module
from antigravity import antigravity

# or an object inside the antigravity module
from antigravity.antigravity import my_object

Ausführung eines einzelnen Testmoduls:

Um ein einzelnes Testmodul auszuführen, in diesem Fall test_antigravity.py :

$ cd new_project
$ python -m unittest test.test_antigravity

Verweisen Sie einfach auf das Testmodul, so wie Sie es importieren.

Ausführung eines einzelnen Testfalls oder einer einzelnen Testmethode:

Sie können auch eine einzelne TestCase oder eine einzige Prüfmethode:

$ python -m unittest test.test_antigravity.GravityTestCase
$ python -m unittest test.test_antigravity.GravityTestCase.test_method

Durchführung aller Tests:

Sie können auch Folgendes verwenden Testentdeckung das alle Tests für Sie entdeckt und ausführt, müssen diese Module oder Pakete sein, die test*.py (kann geändert werden mit dem -p, --pattern Flagge):

$ cd new_project
$ python -m unittest discover
$ # Also works without discover for Python 3
$ # as suggested by @Burrito in the comments
$ python -m unittest

Dadurch werden alle test*.py Module innerhalb der test Paket.

68voto

Patrick Da Silva Punkte 923

Ich habe das gleiche Problem seit langem. Vor kurzem habe ich die folgende Verzeichnisstruktur gewählt:

project_path
 Makefile
 src
    script_1.py
    script_2.py
    script_3.py
 tests
     __init__.py
     test_script_1.py
     test_script_2.py
     test_script_3.py

und in der __init__.py Skript des Testordners schreibe ich das Folgende:

import os
import sys
PROJECT_PATH = os.getcwd()
SOURCE_PATH = os.path.join(
    PROJECT_PATH,"src"
)
sys.path.append(SOURCE_PATH)

Sehr wichtig für die gemeinsame Nutzung des Projekts ist das Makefile, denn es sorgt dafür, dass die Skripte richtig ausgeführt werden. Hier ist der Befehl, den ich in das Makefile eingefügt habe:

run_tests:
    python -m unittest discover .

Das Makefile ist nicht nur wegen des Befehls wichtig, den es ausführt, sondern auch wegen der von wo aus es läuft . Wenn Sie cd in Tests und tun würde python -m unittest discover . würde es nicht funktionieren, weil die init Skript in unit_tests ruft os.getcwd() auf, das dann auf den falschen absoluten Pfad verweisen würde (der an sys.path angehängt würde und Sie würden Ihren Quellordner vermissen). Die Skripte würden laufen, da discover alle Tests findet, aber sie würden nicht richtig laufen. Das Makefile ist also dazu da, um zu vermeiden, dass man sich dieses Problem merken muss.

Ich mag diesen Ansatz sehr, weil ich meinen src-Ordner, meine Unit-Tests oder meine Umgebungsvariablen nicht anfassen muss und alles reibungslos läuft.

57voto

Carl Meyer Punkte 113574

Die einfachste Lösung für Ihre Benutzer ist die Bereitstellung eines ausführbaren Skripts ( runtests.py oder ähnliches), das die notwendige Testumgebung aufbaut, einschließlich, falls erforderlich, des Hinzufügens Ihres Root-Projektverzeichnisses zu sys.path vorübergehend. Dazu müssen die Benutzer keine Umgebungsvariablen setzen, so etwas funktioniert auch in einem Bootstrap-Skript:

import sys, os

sys.path.insert(0, os.path.dirname(__file__))

Dann können Ihre Anweisungen an Ihre Benutzer so einfach sein wie " python runtests.py ".

Natürlich, wenn der Pfad, den Sie benötigen, wirklich os.path.dirname(__file__) dann müssen Sie es nicht zu sys.path überhaupt nicht; Python setzt das Verzeichnis des gerade laufenden Skripts immer an den Anfang von sys.path Je nach Ihrer Verzeichnisstruktur können Sie also einfach Ihre runtests.py an der richtigen Stelle ist vielleicht alles, was nötig ist.

Auch die unittest-Modul in Python 2.7+ (das als "backported" ist ungetestet2 für Python 2.6 und früher) hat jetzt Testentdeckung eingebaut, so dass die Nase nicht mehr notwendig ist, wenn Sie eine automatische Testfindung wünschen: Ihre Benutzeranweisungen können so einfach sein wie python -m unittest discover .

26voto

stw_dev Punkte 812

Im Allgemeinen erstelle ich ein Skript "run tests" im Projektverzeichnis (dasjenige, das sowohl für das Quellverzeichnis als auch für das test ), die meine "Alle Tests"-Suite lädt. Dies ist in der Regel Boilerplate-Code, so dass ich ihn von Projekt zu Projekt wiederverwenden kann.

run_tests.py:

import unittest
import test.all_tests
testSuite = test.all_tests.create_test_suite()
text_runner = unittest.TextTestRunner().run(testSuite)

test/all_tests.py (von Wie kann ich alle Python-Unit-Tests in einem Verzeichnis ausführen? )

import glob
import unittest

def create_test_suite():
    test_file_strings = glob.glob('test/test_*.py')
    module_strings = ['test.'+str[5:len(str)-3] for str in test_file_strings]
    suites = [unittest.defaultTestLoader.loadTestsFromName(name) \
              for name in module_strings]
    testSuite = unittest.TestSuite(suites)
    return testSuite

Mit dieser Einstellung können Sie tatsächlich nur include antigravity in Ihren Testmodulen. Der Nachteil ist, dass Sie mehr Support-Code benötigen, um einen bestimmten Test auszuführen... Ich führe sie einfach jedes Mal aus.

18voto

Mark Byers Punkte 761508

Aus dem Artikel, den Sie verlinkt haben:

Erstellen Sie eine Datei test_modulename.py und fügen Sie Ihre Unittest-Tests darin ein. Da sich die Testmodule in einem anderen von Ihrem Code befinden, müssen Sie möglicherweise das übergeordnete Verzeichnis Ihres Moduls zu Ihrem PYTHONPATH hinzufügen, um sie auszuführen ausführen zu können:

$ cd /path/to/googlemaps

$ export PYTHONPATH=$PYTHONPATH:/path/to/googlemaps/googlemaps

$ python test/test_googlemaps.py

Schließlich gibt es eine weitere beliebte Unit-Test-Framework für Python (so wichtig ist es!), nämlich nose. nose hilft bei der Vereinfachung und Erweiterung des eingebauten unittest-Frameworks (es kann zum Beispiel zum Beispiel automatisch Ihren Testcode finden Code finden und Ihren PYTHONPATH für Sie einrichten einrichten), aber es ist nicht in der Standard-Python-Distribution enthalten.

Vielleicht sollten Sie sich Folgendes ansehen Nase wie sie suggeriert?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X