5

I have an application that I'd like to test using unittest but I have some problems. My directory structure is as follows:

root_dir
├── src
│   ├── cmds
│   │   ├── baz.py
│   │   ├── __init__.py
│   │   └── bar.py
│   └── foo.py
└── tests
    ├── cmds.py
    └── __init__.py

I want to test the baz and bar modules from cmds and I'm trying to do

root_dir> python2.7 -m unittest tests.cmds

But in tests.cmds I cannot import the cmds package in my src dir.

How can I make this work?

Basically I want to test the application from root_dir with the src and tests directories separately.

I tried appending src to sys.path, but when I import cmds.baz from tests/cmds.py I still get an AttributeError: 'module' object has no attribute 'cmds' from unittest.

Edit: My import and sys.path statement is:

import sys
sys.path.append('../src')
from cmds.baz import about

And the traceback:

Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.7/unittest/__main__.py", line 12, in <module>
    main(module=None)
  File "/usr/lib/python2.7/unittest/main.py", line 94, in __init__
    self.parseArgs(argv)
  File "/usr/lib/python2.7/unittest/main.py", line 149, in parseArgs
    self.createTests()
  File "/usr/lib/python2.7/unittest/main.py", line 158, in createTests
    self.module)
  File "/usr/lib/python2.7/unittest/loader.py", line 128, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/usr/lib/python2.7/unittest/loader.py", line 100, in loadTestsFromName
    parent, obj = obj, getattr(obj, part)
AttributeError: 'module' object has no attribute 'cmds'
Paul
  • 20,883
  • 7
  • 57
  • 74
  • 2
    src is not a package but tests is. Why is that? Did you set the python path correctly? – pvoosten Apr 23 '12 at 19:40
  • Show your exact import and the full traceback. – agf Apr 23 '12 at 19:40
  • @lbp Because I must import it when doing `python2.7 -m unittest tests.cmds`. – Paul Apr 24 '12 at 11:56
  • 1
    Maybe it's a problem that your test file is called `cmds.py` and the module directory is called `cmds` - the `module` that has no attribute is probably `cmds.py` - try `import src.cmds.baz` and see if this still gives an error? – BergmannF Apr 24 '12 at 12:04
  • Solved! I ran the test command from the tests directory (not from root ) and renamed tests/cmds.py to something else and I'm still using the import statement posted above. – Paul Apr 24 '12 at 12:16

2 Answers2

5

A very wrong thing to do is appending a relative path to sys.path. If you want to be sure about the path, make it as follows:

# assuming that the code is in test's __init__.py
import os
import sys
sys.path.insert(0, os.path.abspath( os.path.join(os.path.dirname(__file__), 
                                               '../src/') ))
# now you can be sure that the project_root_dir/src comes first in sys.path
Zaur Nasibov
  • 22,280
  • 12
  • 56
  • 83
2

I think you got it almost right. But as you run your tests form the root directory, your path ('../src') is wrong I guess. Maybe you can do something like this:

import os
import sys

ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
sys.path.append(os.path.join(ROOT, 'src'))

from cmds.baz import about
Reto Aebersold
  • 16,306
  • 5
  • 55
  • 74