I want to put all my unit tests in a separate directory. My project layout looks like this:
project
package
__init__.py
package.py
tests
__init__.py
package_test.py
package_test.py looks like:
from unittest import TestCase
from package import Service
class ServiceTest(TestCase):
def test_build():
service = Service.build()
self.assertIsNotNone(service)
When I try to run the tests I get the following error
$ cd project
$ nosetest
E
======================================================================
ERROR: Failure: ImportError (cannot import name 'ScraperService')
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/nose/failure.py", line 39, in runTest
raise self.exc_val.with_traceback(self.tb)
File "/usr/local/lib/python3.6/site-packages/nose/loader.py", line 418, in loadTestsFromName
addr.filename, addr.module)
File "/usr/local/lib/python3.6/site-packages/nose/importer.py", line 47, in importFromPath
return self.importFromDir(dir_path, fqname)
File "/usr/local/lib/python3.6/site-packages/nose/importer.py", line 94, in importFromDir
mod = load_module(part_fqname, fh, filename, desc)
File "/usr/local/lib/python3.6/imp.py", line 234, in load_module
return load_source(name, filename, file)
File "/usr/local/lib/python3.6/imp.py", line 172, in load_source
module = _load(spec)
File "<frozen importlib._bootstrap>", line 675, in _load
File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
File "/usr/src/project/tests/package_test.py", line 2, in <module>
from package import Service
ImportError: cannot import name 'Service'
----------------------------------------------------------------------
Ran 1 test in 0.046s
FAILED (errors=1)
How do I import my package into my test class?
Do I have to make the project a module?
Do I have to package it for distribution with a setup.py
?
To solve your problem, you should change import to be full path, including module directory:
from package.package import Service
The reason because this works is how python loads modules :
Packages are a way of structuring Python's module namespace by using “dotted module names”. For example, the module name AB designates a submodule named B in a package named A. When importing the package, Python searches through the directories on sys.path looking for the package subdirectory.
So, in your project there is package
folder, which contains package.py
file. So in order python could find it, you have to provide full path.
I ran into a similar situation. In my case, I had a folder called
practice/
where various practice problems lived
I had practice/t
where tests for practice problems resided - and I named them the same as the problem itself.
So
practice/calculus.py
was tested by
practice/t/calculus.py
This was what I did to enable this structure:
Inside practice/t/calculus.py:
import sys
sys.path.append('../..')
from practice.calculus import *
This differentiates calculus, the test and calculus, the problem.
It's not clear, this is the right layout for the files - but it does help the understanding of namespaces in python. Unlike many other languages, the namespacing is dynamic, and relative to the user of the module, not the module itself.
If you have a folder structure,
A/B/C/d.py
Then d can be imported as:
from A.B.C.d import *
from B.C.d import *
from C.d import *
from d import *
And you specify what your root is via sys.path.
Of course, sys.path can be specified in your enivonment,
export PYTHONPATH=$PYTHONPATH:/absolute/path/to/AorBorCorD
It's therefore a context-sensitive approach.
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.