2016-07-06 7 views
1

Meine Auswahl Layout ist alsWarum funktioniert der relative Pfad nicht in Python-Tests?

project\ 
project\setup.py 
project\scripts\foo.py 
project\scripts\bar.py 
project\scripts\__init__.py 
project\tests\test_foo.py 
project\tests\__init__.py 

Meine Testdatei

project\tests\test_fo.py 

from ..scripts import foo 

def test_one(): 
    assert 0 

ich folgende Fehlermeldung erhalten, wenn ich

cd C:\project 
C:\virtualenvs\test_env\Scripts\activate 
python setup.py install 
python setup.py test 

E Valueerror wie folgt aussieht folgt: Versuchte relativ Import über das Toplevel-Paket hinaus

Was mache ich falsch? Das ist mein setup.py

setup(
    name = 'project', 
    setup_requires=['pytest-runner'], 
    tests_require=['pytest'], 
    packages = ["scripts","tests"], 
    package_data={ 
      'scripts': ['*.py'], 
      'tests': ['*.py'], 
     }, 
) 

Antwort

3

Relative Importe funktionieren nur innerhalb ein Paket. scripts kann ein Paket sein, und so ist tests, aber das project Verzeichnis ist nicht (und sollte es auch nicht sein). Dies macht scripts und testsTop-Level-Pakete. Sie können nicht auf andere Top-Level-Namen verweisen, indem Sie die relative Syntax verwenden.

Außerdem werden Tests nicht mit dem tests Paket ausgeführt; Der Testläufer importiert das test_foo Modul, nicht das tests.test_foo Modul, also soweit Python betroffen isttest_foo ist ein Top-Level-Modul.

scripts ist ein Top-Level-Name, verwenden Sie das direkt. Sie müssen das Verzeichnis project jedoch zu sys.path hinzufügen. Sie können an der Spitze Ihrer test_foo.py Datei tun dies mit:

import os 
import sys 

TEST_DIR = os.path.dirname(os.path.abspath(__file__)) 
PROJECT_DIR = os.path.abspath(os.path.join(TEST_DIR, os.pardir)) 
sys.path.insert(0, PROJECT_DIR) 

dann von scripts mit absoluten Pfaden importieren:

from scripts import foo 

ist jedoch zu beachten, dass, wenn Sie python setup.py laufen dann Ihr aktuelles Arbeitsverzeichnis hinzugefügt sys.path auf jeden Fall, so scripts ist direkt verfügbar, ohne mit sys.path zu geigen.

Darüber hinaus wird pytest bereits die Arbeit für Sie tun; Für jede gegebene Testdatei wird sichergestellt, dass das erste übergeordnete Verzeichnis mit keine__init__.py Datei in es auf sys.path ist. In Ihrem Fall ist das das project/ Verzeichnis, so dass wieder direkt aus dem Import scripts importiert werden kann.Siehe Good Practices:

If pytest finds a “a/b/test_module.py” test file while recursing into the filesystem it determines the import name as follows:

  • determine basedir : this is the first “upward” (towards the root) directory not containing an __init__.py . If e.g. both a and b contain an __init__.py file then the parent directory of a will become the basedir.
  • perform sys.path.insert(0, basedir) to make the test module importable under the fully qualified import name.
  • import a.b.test_module where the path is determined by converting path separators/into ”.” characters. This means you must follow the convention of having directory and file names map directly to the import names.

Beachten Sie, dass tatsächlich um pytest zu benutzen, um Ihre Tests auszuführen, wenn Sie setup.py test verwenden, benötigen Sie einen Alias ​​in Ihrer setup.cfg-Datei registrieren (erstellen Sie es in project/, wenn Sie noch kein Konto haben):

[aliases] 
test = pytest 
+0

, nachdem ich es zu von Skripten ändern importieren foo ich diesen Fehler (test_123) D: \ Projects \ project> python setup.py Test Lauftest Lauf egg_info Schreiben project.egg-info \ PKG-INFO Top-Level-Namen schriftlich project.egg-info \ top_level.txt Schreiben dependency_links project.egg-info \ dependency_links.txt Manifest-Datei zu lesen 'project.egg-info \ SOURCES.txt' Schreiben der Manifestdatei 'project.egg-info \ SOURCES.txt' läuft build_ext ------------------- -------------------------------------------------- - Lief 0 Tests in 0,000s OK – user330612

+0

@ user330612: Ich werde morgen schauen. –

+0

@ user330612: Beachten Sie den Link "Good Practices" in meiner Antwort. Dort gibt es Infos darüber, dass man der Datei 'setup.cfg' einen Alias ​​hinzufügen muss, bevor' pytest' zum Ausführen der Tests verwendet wird. –