Search code examples
pythonpython-unittestnosepython-module

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?


Solution

  • 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 A.B 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.