124

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.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
halfak
  • 1,716
  • 2
  • 13
  • 17

9 Answers9

235

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.

ire_and_curses
  • 68,372
  • 23
  • 116
  • 141
  • 8
    That got it. Thanks much! I'd up vote, but apparently I need more reputation. – halfak Jun 18 '10 at 22:16
  • 4
    No worries. Welcome to StackOverflow! You can tick the green checkmark to the left if the answer solves your problem. – ire_and_curses Jun 18 '10 at 22:17
  • 2
    @halfak: Have another upvote on your question then. You too (on your answer), @ire. – Mark Rushakoff Jun 18 '10 at 22:18
  • 5
    I have a situation where tests work if __init__.py in root directory - however, I *need* that file to be there, and *import models.* still is not found. Test is inside a *tests/* directory, and the model I'm trying to test is inside *models/* directory... any help would be appreciated. – Kees Briggs Mar 12 '16 at 19:12
  • In addition to __init__.py I had to also remove __init__.pyc . Then nose was able to import a second class. – Tom Anderson Jun 27 '16 at 01:56
  • What if I don't want to remove `__init__.py` because `foo.py` has functions that I'd like to import elsewhere, and I don't want to change the imports because then I'll have to set PYTHONPATH differently inside and outside of nose? This question is also at https://stackoverflow.com/questions/60352884/how-do-i-use-nosetests-with-a-top-level-directory-as-a-package – dfrankow Feb 22 '20 at 19:00
  • Also, why does nose do this, and can I turn off this behavior? Clearly tons of people have trouble with it, since your answer has hundreds of upvotes. – dfrankow Feb 22 '20 at 19:01
35

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
jds
  • 7,910
  • 11
  • 63
  • 101
toppur
  • 1,606
  • 13
  • 12
  • 2
    Also mine. Thank you, saved a lot of time. – jon skulski Aug 27 '15 at 21:46
  • 3
    for me `nosetests` was cached by `bash` to the system one in `/usr/local/bin` (while `which nosetests` was giving the proper result). I used [this](http://unix.stackexchange.com/questions/5609/how-do-i-clear-bashs-cache-of-paths-to-executables) to clear it. – Raffi Nov 20 '15 at 10:20
  • 5
    Additionally, I had to deactivate and activate my virtualenv. – Bengt Feb 20 '16 at 15:51
  • I had a problem with _PS1=${PS1:-}_ set when activating virtualenv (to overcome errors on unset variables). After removing this and switching to _set +u_, I had no problems anymore. – Juuso Ohtonen Jan 17 '18 at 06:24
15

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
robbrit
  • 17,560
  • 4
  • 48
  • 68
11

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.

Aron Ahmadia
  • 2,267
  • 2
  • 19
  • 22
  • @Nakilon http://stackoverflow.com/questions/2064329/why-python-does-not-allow-hyphens – Aman Jun 03 '13 at 19:15
  • 1
    @Aman, you realize difference between variable identifiers and file names? – Nakilon Jun 04 '13 at 08:57
  • Yeah...I always have a file that was similar to FooTests.py and it for some reason didn't like it...I renamed to Foo_Tests.py and it worked...seems a bit finicky. – Birdman Dec 03 '18 at 03:36
4

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
hobs
  • 18,473
  • 10
  • 83
  • 106
4

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

Silly, but happens.

Eyal Levin
  • 16,271
  • 6
  • 66
  • 56
  • Can you please add some details to your answer? What directory did you run it from? Why is it wrong? What would be the right directory? Running `nosetests` in a directory with no tests at all will result in `Ran 0 tests`, not any import error. In its present form this answer is not useful. – gerrit Feb 19 '19 at 10:08
2

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.

7yl4r
  • 4,788
  • 4
  • 34
  • 46
2

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
chehsunliu
  • 1,559
  • 1
  • 12
  • 22
2

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

Rainelz
  • 391
  • 3
  • 8