import error when run tests in submodule with nose

1.1k Views Asked by At

We use git submodule to share common module within our team.

Each module has test cases in its source folder, and ran by nose.

I have a project in this structure:

/project_sample
|__/project_sample
|  |__ __init__.py
|  |__ moduleA.py
|  |__/tests
|  |  |__ __init__.py
|  |  |__ moduleA_tests.py
|  |__/subpackage
|     |__ __init__.py
|     |__ moduleB.py
|     |__/tests
|        |__ __init__.py
|        |__ moduleB_tests.py
|__setup.py

All of these init.py files are empty.

The subpackage is developed seperately and added to the project by git submodule. We want it to be self-contained , and try to share it in different project. Its test case is like this:

moduleB_tests.py:

from subpackage import moduleB

def test_funcA():
    moduleB.funcA()

The test pass when i run nosetests from the subpackage's repo folder.

Seems like nose find a init.py file in the parent folder of subpackage (project_sample), when i run nosetests from project_sample's root directory, i get "ImportError: No module named subpackage". But it passed when i change the first line to:

from project_sample.subpackage import moduleB

But this way makes subpackage not self-contained.

I tried some way like : adding subpackage to sys.path or use -w option of nose, but still get this exception.

My teammate run subpackage's test case seperately in PyCharm and get passed, so i think there should be some way to make it pass from command line.

Is there any way to resolve the problem, or any suggestion with the project structure?

This is my first question on SO, Any suggestion is appreciated.

2

There are 2 best solutions below

5
On BEST ANSWER

If you want subpackage to be self-contained, you need it to treat as such. This means that you need to put it top-level, parallel to project_sample instead of into it.

0
On

I know this question is a bit old and has already been answered but we use a different strategy in our code base.

If for some reason you still want the package in the project_sample module directory, you can structure it something like this:

/project_sample
|__/project_sample
|  |__ __init__.py
|  |__ moduleA.py
|  |__/tests
|  |  |__ __init__.py
|  |  |__ moduleA_tests.py
|  |__/subpackage_repo
|     |__/subpackage
|        |__ __init__.py
|        |__ moduleB.py
|        |__/tests
|           |__ __init__.py
|           |__ moduleB_tests.py
|     |__setup.py
|__setup.py

Without an __init__.py in the subpackage, it won't be a part of your project.

Then in the __init__.py of the main package, you can include

import os
import sys


sys.path.insert(0,
                os.path.join(
                    os.path.dirname(os.path.dirname(__file__)),
                    'subpackage_repo')
)

import subpackage

which puts the subpackage in the path for the main project.

Then in moduleA.py that allows us to do something like

from . import subpackage

since the package is imported at the __init__.py level.

Of course you can also move it up a level as well and just reflect that in the path you're adding if you want to do it that way. The only disadvantage of doing that is that when you run your tests with something like

python -m unittest discover

you'll discover the subpackage tests as well and run those. Ideally those tests should be taken care of with whatever CI you have for the package so we'd hope that they don't need to be run.