简体   繁体   中英

pytest integration - how to properly import

I am using py.test to test my python code. The relevant structure of my project is

-myproject
    file.py
    file2.py
    -test/
        input.txt
        input2.dat
        test_part.py
    -regress/
        file2_old.py
        __init__.py
        -test/
            test_file2_regression.py

test_part.py imports file and file2 and test_file2_regression.py imports file2 and regress.file2_old . If I run pytest in the console, I get the import errors, that the packages don't exist. Running python -m pytest on the other hand works perfectly fine, but only if I run it from the myproject/ directory.

What is the correct way to do this, to get it working from anywhere in my project? I already tried modifying the PYTHONPATH but I honestly have no idea how to properly do it.


Further information:

I don't have any setup files, and my __init__ s are just empty files. If manipulating the PYTHONPATH is necessary it needs to be done relative to myproject as I use it on several machines. I am running python 2.7.


I already check out:

but it didn't really help me.

The solution which works with the pytest command from any directory in the project is to include before the imports in the test*.py files:

import os
from sys import path
PATH = os.path.abspath(os.path.dirname(__file__))
path.append(os.path.join(PATH, os.pardir, os.pardir))

where the proper number of os.pardir is used to navigate to the project directory, from there the __init__.py files allow to import the modules.

Both argv[0] and inspect.getsourcefile don't provide the necessary information. argv[0] contains the location of the used py.test module and the getsourcefile method simply returns None .


Edit: since Python 3.4 we can use instead of os.path the modern pathlib :

from pathlib import Path
from sys import path

PATH = Path(__file__).resolve()
path.append(PATH.parents[2])

Having the same issue and similar success in searching for "the best way of doing this", I concluded for myself to avoid the situation whenever possible (by running the actual scripts consequently from top level), but to answer your question, my current approach (for instance for unit testing from a parallel folder) is

from sys import argv, path
from os.path import dirname, join
path.append(join(dirname(argv[0]), ".."))

This makes the interpreter also search in the folder above where the script is started. Another approach (instead of using argv ) is to use the introspect module to obtain the filename. These work better for me than using __file__ , as the latter is not always defined.

Edit 29.10.: Alternative to argv[0] is to use

from inspect import getsourcefile
from sys import path
from os.path import dirname, join

this_file = getsourcefile(lambda _: None)
path.append(join(dirname(this_file), ".."))

I hope this will work at least for the requested purpose, see also How do I get the path of the current executed file in Python? .

The simplest - if it works in your case - is of course:

from os.path import dirname, join
path.append(join(dirname(__file__), ".."))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM