问题
Unlike in this question:
Importing modules from a sibling directory for use with py.test
I can import something from my app, but there's an import error (looking like a circular dependency) that raises from 'inside' myapp
while running the test and not when running myapp
alone:
$ python3 myapp/myapp.py
Some dummy string (correct output)
But:
$ python3 -m pytest
================================================================= test session starts =================================================================
platform linux -- Python 3.4.3, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/nico/temp/projects_structures/test04/myapp, inifile:
plugins: cov-2.2.1
collected 0 items / 1 errors
======================================================================= ERRORS ========================================================================
________________________________________________________ ERROR collecting tests/test_things.py ________________________________________________________
tests/test_things.py:4: in <module>
from myapp.lib.core.base import do_things
myapp/lib/core/base.py:1: in <module>
from lib import something
E ImportError: No module named 'lib'
=============================================================== 1 error in 0.05 seconds ===============================================================
As you can see, the problem is not the import
statement from the test file. It's raised from 'inside' myapp
.
Here is the complete structure:
.
└── myapp
├── myapp
│ ├── __init__.py
│ ├── lib
│ │ ├── core
│ │ │ ├── base.py
│ │ │ └── __init__.py
│ │ └── __init__.py
│ └── myapp.py
└── tests
└── test_things.py
myapp.py contains:
#!/usr/bin/env python3
from lib.core import base
base.do_things()
lib/__init__.py contains:
something = "Some dummy string (correct output)"
base.py contains:
from lib import something
def do_things():
print(something)
return True
and test_things contains:
import unittest
import sys
sys.path.insert(0, '..')
from myapp.lib.core.base import do_things
class DoThingsTestCase(unittest.TestCase):
def test_do_things(self):
self.assertTrue(do_things())
if __name__ == '__main__':
unittest.main()
And $PYTHONPATH
seems correctly set (so this:
Py.test No module named *
doesn't answer my problem). (Or if this is not correct, how can I correct it?)
$ echo $PYTHONPATH
/home/nico/temp/projects_structures/test04/myapp/myapp
回答1:
Setting the PYTHONPATH should do the trick.
$ export PYTHONPATH=<ABSOLUTE PATH TO TOPMOST myapp dir>
(in this example, it is the path to myapp/myapp; and ensure you've exported PYTHONPATH
, not only set it).
and from myapp run either
$ py.test
or
$ python3 -m pytest
回答2:
Another way of doing this is to put a conftest.py
file into the top level of myapp
, or in myapp/tests
. Like this:
$ pwd
/home/nico/temp/projects_structures/test04/myapp/tests
$ touch conftest.py
$ cd ..
$ py.test
================================================================= test session starts =================================================================
platform linux2 -- Python 2.7.6, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/nico/temp/projects_structures/test04/myapp, inifile:
collected 1 items
tests/test_things.py .
============================================================== 1 passed in 0.05 seconds ===============================================================
$
(and PYTHONPATH
is empty:
$ echo $PYTHONPATH
$
)
This way, py.test
automatically adds myapp
to PYTHONPATH
. This avoids to forget exporting PYTHONPATH
and will make the tests of myapp
easier for other devs (who neither will need to solve this problem).
来源:https://stackoverflow.com/questions/37560196/importerror-shows-up-with-py-test-but-not-when-running-the-app