Python Nose Import Error

2019-01-07 06:25发布

问题:

I can't seem to get the nose testing framework to recognize modules beneath my test script in the file structure. I've set up the simplest example that demonstrates the problem. I'll explain it below.

Here's the the package file structure:

./__init__.py
./foo.py
./tests
   ./__init__.py
   ./test_foo.py

foo.py contains:

def dumb_true():
    return True

tests/test_foo.py contains:

import foo

def test_foo():
    assert foo.dumb_true()

Both init.py files are empty

If I run nosetests -vv in the main directory (where foo.py is), I get:

Failure: ImportError (No module named foo) ... ERROR

======================================================================
ERROR: Failure: ImportError (No module named foo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/loader.py", line 379, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/importer.py", line 39, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/importer.py", line 86, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/home/user/nose_testing/tests/test_foo.py", line 1, in <module>
    import foo
ImportError: No module named foo

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (errors=1)

I get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from which it is called, but this doesn't seem to be happening in my case.

I'm running Ubuntu 8.04 with Python 2.6.2. I've built and installed nose manually (not with setup_tools) if that matters.

回答1:

You've got an __init__.py in your top level directory. That makes it a package. If you remove it, your nosetests should work.

If you don't remove it, you'll have to change your import to import dir.foo, where dir is the name of your directory.



回答2:

Are you in a virtualenv? In my case, nosetests was the one in /usr/bin/nosetests, which was using /usr/bin/python. The packages in the virtualenv definitely won't be in the system path. The following fixed this:

source myvirtualenv/activate
pip install nose
which nosetests
/home/me/myvirtualenv/bin/nosetests


回答3:

To those of you finding this question later on: I get the import error if I don't have an __init__.py file in my tests directory.

My directory structure was like this:

./tests/
  ./test_some_random_stuff.py

If I ran nosetests:

nosetests -w tests

It would give the ImportError that everyone else is seeing. If I add a blank __init__.py file it works just fine:

./tests/
  ./__init__.py
  ./test_some_random_stuff.py


回答4:

Another potential problem appears to be hyphens/dashes in the directory tree. I recently fixed a nose ImportError issue by renaming a directory from sub-dir to sub_dir.



回答5:

I got this error message because I run the nosetests command from the wrong directory.

Silly, but happens.



回答6:

Of course if you have a syntax error in the module being imported that will cause this. For me the problem reared its head when I had a backup of a tests file with a path like module/tests.bak.py in the same directory as tests.py. Also, to deal with the init package/module problem in a Django app, you can run the following (in a bash/OSX shell) to make sure you don't have any init.pyc files lying around:

find . -name '*.pyc' -delete


回答7:

For example, with the following directory structure, if you want to run nosetests in m1, m2 or m3 to test some functions in n.py, you should use from m2.m3 import n in test.py.

m1
└── m2
    ├── __init__.py
    └── m3
        ├── __init__.py
        ├── n.py
        └── test
            └── test.py


回答8:

I just ran into one more thing that might cause this issue: naming of tests in the form testname.test.py. That extra . confounds nose and leads to it importing things it should not. I suppose it may be obvious that using unconventional test naming conventions will break things, but I thought it might be worth noting.



回答9:

Just to complete the question: If you're struggling with structure like this:

project
├── m1
├    ├── __init__.py
├    ├── foo1.py
├    └──m2
├       ├── __init__.py
├       └── foo2.py
├
└── test
     ├── __init__.py
     └── test.py

And maybe you want to run test from a path outside the project, include your project path inside your PYTHONPATH.

export PYTHONPATH=$PYTHONPATH:$HOME/path/to/project

paste it inside your .profile. If you're under a virtual environment, paste it inside the activate in your venv root