Unittest mit typischer Testverzeichnisstruktur ausführen

699

Die sehr verbreitete Verzeichnisstruktur selbst für ein einfaches Python-Modul scheint darin zu bestehen, die Komponententests in ein eigenes testVerzeichnis zu unterteilen:

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

Sehen Sie sich zum Beispiel dieses Python-Projekt-Howto an .

Meine Frage ist einfach: Wie werden die Tests normalerweise ausgeführt? Ich vermute, dass dies für alle außer mir offensichtlich ist, aber Sie können nicht einfach vom Testverzeichnis python test_antigravity.pyaus ausführen, da dies import antigravityfehlschlagen wird, da sich das Modul nicht auf dem Pfad befindet.

Ich weiß, dass ich PYTHONPATH und andere Tricks im Zusammenhang mit Suchpfaden ändern könnte, aber ich kann nicht glauben, dass dies der einfachste Weg ist - es ist in Ordnung, wenn Sie der Entwickler sind, aber nicht realistisch, von Ihren Benutzern zu erwarten, dass sie sie verwenden, wenn sie nur die Tests überprüfen möchten Vorbeigehen.

Die andere Alternative besteht darin, die Testdatei nur in das andere Verzeichnis zu kopieren, aber es scheint ein bisschen dumm zu sein und es fehlt der Sinn, sie zunächst in einem separaten Verzeichnis zu haben.

Wenn Sie also gerade die Quelle in mein neues Projekt heruntergeladen hätten, wie würden Sie die Komponententests durchführen? Ich würde eine Antwort bevorzugen, mit der ich meinen Benutzern sagen könnte: "Um die Komponententests auszuführen, machen Sie X."

Major Major
quelle
5
@EMP Die richtige Lösung, wenn Sie den Suchpfad festlegen müssen, besteht darin, ... den Suchpfad festzulegen. Welche Art von Lösung haben Sie erwartet?
Carl Meyer
7
@CarlMeyer Eine weitere bessere Lösung ist die Verwendung der unittestBefehlszeilenschnittstelle, wie in meiner Antwort unten beschrieben, damit Sie das Verzeichnis nicht zum Pfad hinzufügen müssen.
Pierre
13
Hier gilt das gleiche. Ich habe gerade angefangen, meine ersten Unit-Tests für ein winziges Python-Projekt zu schreiben, und habe mehrere Tage gebraucht, um zu begründen, dass ich einen Test nicht ohne weiteres ausführen kann, während ich meine Quellen in einem src-Verzeichnis und Tests in einem Testverzeichnis halte. scheinbar mit einem der vorhandenen Test-Frameworks. Ich werde irgendwann Dinge akzeptieren, einen Weg finden; Dies war jedoch eine sehr frustrierende Einführung. (Und ich bin ein Unit-Test-Veteran außerhalb von Python.)
Ates Goral

Antworten:

655

Die beste Lösung ist meiner Meinung nach, die unittest Befehlszeilenschnittstelle zu verwenden, die das Verzeichnis zu dem hinzufügt, sys.pathdamit Sie es nicht müssen (in der TestLoaderKlasse erledigt ).

Zum Beispiel für eine Verzeichnisstruktur wie diese:

new_project
├── antigravity.py
└── test_antigravity.py

Sie können einfach ausführen:

$ cd new_project
$ python -m unittest test_antigravity

Für eine Verzeichnisstruktur wie 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 des testPakets können Sie das antigravityPaket und seine Module wie gewohnt importieren :

# 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ühren eines einzelnen Testmoduls:

So führen Sie ein einzelnes Testmodul aus test_antigravity.py:

$ cd new_project
$ python -m unittest test.test_antigravity

Referenzieren Sie das Testmodul genauso wie Sie es importieren.

Ausführen eines einzelnen Testfalls oder einer Testmethode:

Sie können auch eine einzelne TestCaseoder eine einzelne Testmethode ausführen :

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

Alle Tests ausführen:

Sie können auch mit Test Entdeckung , die alle Tests für Sie entdecken und ausführen können , müssen sie benannt Module oder Pakete sein test*.py(kann mit der geändert werden -p, --patternflag):

$ 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*.pyModule im testPaket ausgeführt.

Pierre
quelle
53
python -m unittest discoverfindet Tests im testVerzeichnis und führt sie aus, wenn sie benannt sind test*.py. Wenn Sie das Unterverzeichnis benannt haben tests, verwenden Sie python -m unittest discover -s tests, und wenn Sie die Testdateien benannt haben antigravity_test.py, verwenden Sie python -m unittest discover -s tests -p '*test.py' Dateinamen können Unterstriche, aber keine Bindestriche verwenden.
Mike3d0g
10
Dies schlägt für mich unter Python 3 mit dem Fehler ImportError: No module named 'test.test_antigravity'aufgrund eines Konflikts mit dem Test-Submodul der unittest-Bibliothek fehl . Möglicherweise kann ein Experte den Namen des Antwort-Unterverzeichnisses bestätigen und in "Tests" (Plural) ändern.
Expz
9
Mein test_antigravity.pywirft immer noch einen Importfehler für beide import antigravityund from antigravity import antigravityauch. Ich habe beide __init_.pyDateien und rufe python3 -m unittest discoveraus dem new projectVerzeichnis an. Was könnte sonst noch falsch sein?
Imrek
19
Datei test/__init__.pyist hier entscheidend, auch wenn leer
Francois
3
@ Mike3d0g nicht sicher, ob Sie implizieren wollten, dass der Verzeichnisname etwas testBesonderes ist ... aber nur für den Datensatz ist es nicht. : P python -m unittest discoverfunktioniert mit Testdateien tests/genauso gut wie test/.
Ryan
49

Die einfachste Lösung für Ihre Benutzer besteht darin, ein ausführbares Skript ( runtests.pyoder ein solches) bereitzustellen, das die erforderliche Testumgebung bootet und bei Bedarf Ihr Stammprojektverzeichnis sys.pathvorübergehend hinzufügt . Dies erfordert nicht, dass Benutzer Umgebungsvariablen festlegen. So etwas funktioniert in einem Bootstrap-Skript einwandfrei:

import sys, os

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

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

Wenn der Pfad, den Sie wirklich benötigen, wirklich ist os.path.dirname(__file__), müssen Sie ihn natürlich überhaupt nicht hinzufügen sys.path. Python setzt das Verzeichnis des aktuell ausgeführten Skripts immer an den Anfang von sys.path. Abhängig von Ihrer Verzeichnisstruktur ist runtests.pyes möglicherweise alles, was Sie benötigen , um Ihr Verzeichnis an der richtigen Stelle zu finden.

Auch das Unittest - Modul in Python 2.7+ (die als zurückportiert wird unittest2 für Python 2.6 und früher) hat nun Test Entdeckung eingebaut, so Nase ist nicht mehr erforderlich , wenn Sie automatisierte Test Entdeckung wollen: Ihre Benutzeranweisungen können so einfach wie python -m unittest discover.

Carl Meyer
quelle
Ich habe einige Tests in einen Unterordner wie "Major Major" gestellt. Sie können mit Python -m ausgeführt werden, aber wie kann ich auswählen, dass nur einer von ihnen ausgeführt wird? Wenn ich python -m unittest tests / testxxxxx ausführe, schlägt das Pfadproblem fehl. Da der Dicovery-Modus alles löst, würde ich erwarten, dass es einen anderen Trick gibt, um das Pfadproblem zu lösen, ohne die Pfadkorrektur zu handcodieren, die Sie im ersten Punkt vorschlagen
Frederic Bazin
2
@FredericBazin Verwenden Sie Discovery nicht, wenn Sie nur einen einzigen Test oder eine einzelne Testdatei möchten. Benennen Sie einfach das Modul, das Sie ausführen möchten. Wenn Sie es als gepunkteten Modulpfad (und nicht als Dateipfad) bezeichnen, kann es den Suchpfad korrekt ermitteln. Siehe Peters Antwort für weitere Details.
Carl Meyer
Dieser Hack war nützlich in einem Szenario, in dem ich so etwas ausführen musste python -m pdb tests\test_antigravity.py. In pdb habe ich ausgeführt sys.path.insert(0, "antigravity"), wodurch die import-Anweisung aufgelöst werden konnte, als würde ich das Modul ausführen .
ixe013
23

Im Allgemeinen erstelle ich im Projektverzeichnis ein Skript zum Ausführen von Tests (das sowohl für das Quellverzeichnis als auch für das Quellverzeichnis gilt test), das meine Suite "Alle Tests" lädt. Dies ist normalerweise Boilerplate-Code, sodass 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 führe ich alle Python- Komponententests in einem Verzeichnis aus? )

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 diesem Setup können Sie in der Tat nur include antigravityin Ihren Testmodulen. Der Nachteil ist, dass Sie mehr Support-Code benötigen, um einen bestimmten Test auszuführen ... Ich führe sie jedes Mal aus.

stw_dev
quelle
1
Ich wollte auch ein run testsSkript im Projektverzeichnis und fand einen viel saubereren Weg , dies zu tun. Sehr empfehlenswert.
z33k
18

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 von Ihrem Code getrennten Verzeichnis befinden, müssen Sie möglicherweise das übergeordnete Verzeichnis Ihres Moduls zu Ihrem PYTHONPATH hinzufügen, um sie auszuführen:

$ cd /path/to/googlemaps

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

$ python test/test_googlemaps.py

Schließlich gibt es ein weiteres beliebtes Unit-Testing-Framework für Python (so wichtig!), Die Nase. Mit der Nase können Sie das integrierte Framework vereinfachen und erweitern (es kann beispielsweise Ihren Testcode automatisch finden und Ihren PYTHONPATH für Sie einrichten), ist jedoch nicht in der Standard-Python-Distribution enthalten.

Vielleicht sollten Sie sich die Nase ansehen, wie es nahelegt?

Mark Byers
quelle
3
Ja, das funktioniert (für mich), aber ich bitte wirklich um die einfachsten Anweisungen, die ich Benutzern für mein Modul geben kann, damit sie die Tests ausführen. Das Ändern des Pfades mag es tatsächlich sein, aber ich fische nach etwas Unkomplizierterem.
Major Major
4
Wie sieht Ihr Python-Pfad aus, nachdem Sie an hundert Projekten gearbeitet haben? Soll ich manuell hineingehen und meinen Weg bereinigen? Wenn ja, ist dies ein abscheuliches Design!
Jeremyjjbrown
11

Ich hatte das gleiche Problem mit einem separaten Ordner für Komponententests. Aus den genannten Vorschlägen füge ich den absoluten Source - Pfad zu sys.path.

Der Vorteil der folgenden Lösung besteht darin, dass die Datei ausgeführt werden kann, test/test_yourmodule.pyohne zunächst in das Testverzeichnis zu wechseln:

import sys, os
testdir = os.path.dirname(__file__)
srcdir = '../antigravity'
sys.path.insert(0, os.path.abspath(os.path.join(testdir, srcdir)))

import antigravity
import unittest
andpei
quelle
9

Wenn Sie "python setup.py Develop" ausführen, befindet sich das Paket im Pfad. Möglicherweise möchten Sie dies jedoch nicht tun, da Sie Ihre Systempython- Installation infizieren könnten. Aus diesem Grund gibt es Tools wie virtualenv und buildout .

Tom Willis
quelle
7

Lösung / Beispiel für Python unittest Modul

Bei folgender Projektstruktur:

ProjectName
 ├── project_name
 |    ├── models
 |    |    └── thing_1.py
 |    └── __main__.py
 └── test
      ├── models
      |    └── test_thing_1.py
      └── __main__.py

Sie können Ihr Projekt aus dem Stammverzeichnis ausführen, mit python project_namedem aufgerufen wird ProjectName/project_name/__main__.py.


Um Ihre Tests python testeffektiv auszuführen ProjectName/test/__main__.py, müssen Sie Folgendes tun:

1) Verwandeln Sie Ihr test/modelsVerzeichnis in ein Paket, indem Sie eine __init__.pyDatei hinzufügen . Dadurch können Sie auf die Testfälle im Unterverzeichnis über das übergeordnete testVerzeichnis zugreifen .

# ProjectName/test/models/__init__.py

from .test_thing_1 import Thing1TestCase        

2) Ändern Sie Ihren Systempfad so test/__main__.py, dass er das project_nameVerzeichnis enthält.

# ProjectName/test/__main__.py

import sys
import unittest

sys.path.append('../project_name')

loader = unittest.TestLoader()
testSuite = loader.discover('test')
testRunner = unittest.TextTestRunner(verbosity=2)
testRunner.run(testSuite)

Jetzt können Sie erfolgreich Dinge aus project_nameIhren Tests importieren .

# ProjectName/test/models/test_thing_1.py    

import unittest
from project_name.models import Thing1  # this doesn't work without 'sys.path.append' per step 2 above

class Thing1TestCase(unittest.TestCase):

    def test_thing_1_init(self):
        thing_id = 'ABC'
        thing1 = Thing1(thing_id)
        self.assertEqual(thing_id, thing.id)
Derek Soike
quelle
5

Verwenden setup.py developSie diese Option , um Ihr Arbeitsverzeichnis Teil der installierten Python-Umgebung zu machen, und führen Sie dann die Tests aus.

Ned Batchelder
quelle
Dies bringt mir eine invalid command 'develop'und diese Option wird nicht erwähnt, wenn ich danach frage setup.py --help-commands. Muss es etwas an setup.pysich geben, damit dies funktioniert?
Major Major
Es ist in Ordnung - das Problem war, dass ich eine import setuptoolsin meiner setup.pyDatei vermisst habe . Aber ich denke, das zeigt, dass dies für die Module anderer Leute nicht immer funktioniert.
Major Major
1
Wenn Sie pip haben , können Sie damit Ihr Paket im "bearbeitbaren" Modus installieren : pip install -e .Dadurch wird das Paket ebenfalls zur Python-Umgebung hinzugefügt, ohne die Quelle zu kopieren, sodass Sie es dort weiter bearbeiten können, wo es liegt.
Eric Smith
pip install -e .ist genau das Gleiche wie python setup.py develop, es setup.pypasst nur dazu, Setuptools zu verwenden, auch wenn dies nicht der Fall ist, also funktioniert es so oder so.
Carl Meyer
5

Wenn Sie VS-Code verwenden und sich Ihre Tests auf derselben Ebene wie Ihr Projekt befinden, funktioniert das Ausführen und Debuggen Ihres Codes nicht sofort. Sie können Ihre Datei launch.json ändern:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "program": "${file}",
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.env",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }    
    ]
}

Die Schlüsselzeile hier ist envFile

"envFile": "${workspaceRoot}/.env",

Fügen Sie im Stammverzeichnis Ihres Projekts die ENV-Datei hinzu

Fügen Sie innerhalb Ihrer .env-Datei einen Pfad zum Stammverzeichnis Ihres Projekts hinzu. Dies wird vorübergehend hinzugefügt

PYTHONPATH = C: \ IHR \ PYTHON \ PROJECT \ ROOT_DIRECTORY

Wenn Sie den Pfad zu Ihrem Projekt eingeben, können Sie Debug-Unit-Tests aus VS Code verwenden

Vlad Bezden
quelle
5

Ich habe festgestellt, dass Importe ohne Änderungen korrekt funktionieren, wenn Sie die unittest-Befehlszeilenschnittstelle von Ihrem "src" -Verzeichnis aus ausführen.

python -m unittest discover -s ../test

Wenn Sie dies in eine Batchdatei in Ihrem Projektverzeichnis einfügen möchten, können Sie dies tun:

setlocal & cd src & python -m unittest discover -s ../test
Alan L.
quelle
5

Ich habe seit langer Zeit das gleiche Problem. Was ich kürzlich gewählt habe, ist die folgende Verzeichnisstruktur:

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 im __init__.pySkript des Testordners schreibe ich Folgendes:

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

Super wichtig für die Freigabe des Projekts ist das Makefile, da es die ordnungsgemäße Ausführung der Skripte erzwingt. 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 ausgeführten Befehls wichtig, sondern auch, weil es von dort aus ausgeführt wird . Wenn Sie in Tests cd und tun würden python -m unittest discover ., würde es nicht funktionieren, weil der init ausführen Skript in unit_tests os.getcwd () aufruft, das dann auf den falschen absoluten Pfad verweist (der an sys.path angehängt wird und Sie fehlen würden Ihr Quellordner). Die Skripte würden ausgeführt, da Discovery alle Tests findet, aber sie würden nicht ordnungsgemäß ausgeführt. Das Makefile soll also verhindern, dass Sie sich an dieses Problem erinnern müssen.

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

Lass es mich wissen, wenn es euch gefällt.

Ich hoffe, das hilft,

Patrick Da Silva
quelle
4

Folgendes ist meine Projektstruktur:

ProjectFolder:
 - project:
     - __init__.py
     - item.py
 - tests:
     - test_item.py

Ich fand es besser, in die setUp () -Methode zu importieren:

import unittest
import sys    

class ItemTest(unittest.TestCase):

    def setUp(self):
        sys.path.insert(0, "../project")
        from project import item
        # further setup using this import

    def test_item_props(self):
        # do my assertions

if __name__ == "__main__":
    unittest.main()
Rolika
quelle
4

Was ist die übliche Art, die Tests tatsächlich auszuführen?

Ich benutze Python 3.6.2

cd new_project

pytest test/test_antigravity.py

So installieren Sie pytest :sudo pip install pytest

Ich habe keine Pfadvariable festgelegt und meine Importe schlagen nicht mit derselben "Test" -Projektstruktur fehl.

Ich habe dieses Zeug auskommentiert: if __name__ == '__main__'so:

test_antigravity.py

import antigravity

class TestAntigravity(unittest.TestCase):

    def test_something(self):

        # ... test stuff here


# if __name__ == '__main__':
# 
#     if __package__ is None:
# 
#         import something
#         sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
#         from .. import antigravity
# 
#     else:
# 
#         from .. import antigravity
# 
#     unittest.main()
aliopi
quelle
4

Es ist möglich, einen Wrapper zu verwenden, der ausgewählte oder alle Tests ausführt.

Zum Beispiel:

./run_tests antigravity/*.py

oder um alle Tests rekursiv auszuführen, verwenden Sie globbing ( tests/**/*.py) (enable by shopt -s globstar).

Der Wrapper kann grundsätzlich argparsedie folgenden Argumente analysieren:

parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='*')

Laden Sie dann alle Tests:

for filename in args.files:
    exec(open(filename).read())

Fügen Sie sie dann Ihrer Testsuite hinzu (mit inspect):

alltests = unittest.TestSuite()
for name, obj in inspect.getmembers(sys.modules[__name__]):
    if inspect.isclass(obj) and name.startswith("FooTest"):
        alltests.addTest(unittest.makeSuite(obj))

und führen Sie sie:

result = unittest.TextTestRunner(verbosity=2).run(alltests)

Überprüfen Sie dieses Beispiel für weitere Details.

Siehe auch: Wie werden alle Python-Komponententests in einem Verzeichnis ausgeführt?

Kenorb
quelle
4

Python 3+

Hinzufügen zu @Pierre

Verwenden Sie die unittestVerzeichnisstruktur wie folgt:

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

So führen Sie das Testmodul aus test_antigravity.py:

$ cd new_project
$ python -m unittest test.test_antigravity

Oder eine einzelne TestCase

$ python -m unittest test.test_antigravity.GravityTestCase

Obligatorisch nicht vergessen, __init__.pyauch wenn leer, sonst funktioniert es nicht.

eusoubrasileiro
quelle
2

Sie können nicht ohne Voodoo aus dem übergeordneten Verzeichnis importieren. Hier ist noch eine andere Möglichkeit, die mit mindestens Python 3.6 funktioniert.

Erstellen Sie zunächst eine Datei test / context.py mit folgendem Inhalt:

import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

Führen Sie dann den folgenden Import in die Datei test / test_antigravity.py durch:

import unittest
try:
    import context
except ModuleNotFoundError:
    import test.context    
import antigravity

Beachten Sie, dass der Grund für diese Try-Except-Klausel der folgende ist

  • Der Import von test.context schlägt fehl, wenn er mit "python test_antigravity.py" und ausgeführt wird
  • Der Importkontext schlägt fehl, wenn er mit "python -m unittest" aus dem Verzeichnis new_project ausgeführt wird.

Mit diesem Trick arbeiten beide.

Jetzt können Sie alle Testdateien im Testverzeichnis ausführen mit:

$ pwd
/projects/new_project
$ python -m unittest

oder führen Sie eine einzelne Testdatei aus mit:

$ cd test
$ python test_antigravity

Ok, es ist nicht viel schöner als den Inhalt von context.py in test_antigravity.py zu haben, aber vielleicht ein bisschen. Vorschläge sind willkommen.

tjk
quelle
2

Wenn Ihr Testverzeichnis mehrere Verzeichnisse enthält, müssen Sie jedem Verzeichnis eine __init__.pyDatei hinzufügen .

/home/johndoe/snakeoil
└── test
    ├── __init__.py        
    └── frontend
        └── __init__.py
        └── test_foo.py
    └── backend
        └── __init__.py
        └── test_bar.py

Um dann jeden Test auf einmal auszuführen, führen Sie Folgendes aus:

python -m unittest discover -s /home/johndoe/snakeoil/test -t /home/johndoe/snakeoil

Quelle: python -m unittest -h

  -s START, --start-directory START
                        Directory to start discovery ('.' default)
  -t TOP, --top-level-directory TOP
                        Top level directory of project (defaults to start
                        directory)
Qlimax
quelle
1

Dieses BASH-Skript führt das Python-Unittest-Testverzeichnis von einer beliebigen Stelle im Dateisystem aus, unabhängig davon, in welchem ​​Arbeitsverzeichnis Sie sich befinden.

Dies ist nützlich, wenn Sie im ./srcoder ./exampleArbeitsverzeichnis bleiben und einen schnellen Komponententest benötigen:

#!/bin/bash

this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"

python -m unittest discover -s "$readlink"/test -v

Es ist keine test/__init__.pyDatei erforderlich, um den Paket- / Speicheraufwand während der Produktion zu belasten.

John Greene
quelle
1

Auf diese Weise können Sie die Testskripte von jedem beliebigen Ort aus ausführen, ohne mit Systemvariablen über die Befehlszeile herumzuspielen.

Dadurch wird der Hauptprojektordner zum Python-Pfad hinzugefügt, wobei der Speicherort relativ zum Skript selbst und nicht relativ zum aktuellen Arbeitsverzeichnis gefunden wird.

import sys, os

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

Fügen Sie das oben in all Ihren Testskripten hinzu. Dadurch wird der Hauptprojektordner zum Systempfad hinzugefügt, sodass alle Modulimporte, die von dort aus funktionieren, jetzt funktionieren. Und es spielt keine Rolle, von wo aus Sie die Tests ausführen.

Sie können die Datei project_path_hack natürlich so ändern, dass sie dem Speicherort Ihres Hauptprojektordners entspricht.

Chasmani
quelle
0

Wenn Sie nach einer Nur-Befehlszeilenlösung suchen:

Basierend auf der folgenden Verzeichnisstruktur (verallgemeinert mit einem dedizierten Quellverzeichnis):

new_project/
    src/
        antigravity.py
    test/
        test_antigravity.py

Windows : (in new_project)

$ set PYTHONPATH=%PYTHONPATH%;%cd%\src
$ python -m unittest discover -s test

Siehe diese Frage, wenn Sie diese in einer Batch-for-Schleife verwenden möchten.

Linux : (in new_project)

$ export PYTHONPATH=$PYTHONPATH:$(pwd)/src  [I think - please edit this answer if you are a Linux user and you know this]
$ python -m unittest discover -s test

Mit diesem Ansatz ist es auch möglich, dem PYTHONPATH bei Bedarf weitere Verzeichnisse hinzuzufügen.

pj.dewitte
quelle
0

Sie sollten das Pip-Tool wirklich verwenden.

Verwenden Sie pip install -e .diese Option, um Ihr Paket im Entwicklungsmodus zu installieren. Dies ist eine sehr gute Vorgehensweise, die von pytest empfohlen wird (siehe die Dokumentation zu bewährten Vorgehensweisen , in der Sie auch zwei Projektlayouts finden, denen Sie folgen können).

Tintenfisch
quelle
Warum diese Antwort ablehnen? Ich habe die akzeptierte Antwort gelesen und obwohl es nicht schlecht war, pytestist es viel besser, Tests durchzuführen, da die Konsolenausgabe in Farbe mit Stapelverfolgungsinformationen und detaillierten Informationen zu Assertionsfehlern angezeigt wird.
Aliopi