简体   繁体   中英

Python unittest import module with nostest

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.

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