问题
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