2

Does nosetests treat directories with certain names differently? Is a src directory special?

If I have a project whose source directory is named src, nosetests seems to work fine. However, if the directory is named anything else, nosetests reports a bunch of import errors.

Here's what I did:

  1. run tests

    ~/src$ nosetests
    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.001s
    
    OK
    
  2. rename directory

    ~/src$ cd ..
    ~/$ mv src/ src2
    
  3. rerun tests

    ~/$ cd src2
    ~/src2$ nosetests
    E
    ======================================================================
    ERROR: Failure: ImportError (No module named **whatever**)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
    ... etc. ...
        import **whatever**
    ImportError: No module named **whatever**
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.001s
    
    FAILED (errors=1) 
    

I wasn't able to find anything in the docs about this.


Example: with this directory structure:

.
|-- a
|   |-- b.py
|   `-- __init__.py
|-- __init__.py
`-- test
    |-- a
    |   |-- __init__.py
    |   `-- testb.py
    `-- __init__.py

all __init__.py files are empty, the contents of a/b.py are:

y = 3

and of test/a/testb.py:

import a.b
import unittest as u


class TestB(u.TestCase):

    def test1(self):
        self.assertTrue(True)

    def test2(self):
        self.assertTrue(False)

I can reliably reproduce this problem. Running nosetests -V gives:

nosetests version 1.2.1
Matt Fenwick
  • 48,199
  • 22
  • 128
  • 192
  • Should be smth simple. what imports do you have in your tests? – alecxe Apr 24 '13 at 13:37
  • Quite a few, and the exact same imports in both cases. Do you think a specific import could be causing a problem? If so, why when the directory is not named `src`, but not when it is? – Matt Fenwick Apr 24 '13 at 18:36
  • Well, I haven't reproduced it with one simple test case in the directory. Something in your tests (or smth that they import) requires `src` module to exist. Could you please just leave one simple test without any imports except `TestCase` class and try the same thing again? – alecxe Apr 24 '13 at 20:55
  • @AlexanderAfanasiev I've added an example. There's no mention of `src` anywhere in it, though. I'm really stumped. :( – Matt Fenwick Apr 25 '13 at 14:15
  • 1
    I've created mentioned directory structure locally and yes, I've reproduced it. Interesting fact: if you remove `__init__.py` from the root dir - it'll work. – alecxe Apr 25 '13 at 14:24
  • @AlexanderAfanasiev wow, that's blowing my mind! I have no idea why it works that way. Thanks! – Matt Fenwick Apr 25 '13 at 14:55
  • @alecxe no, I haven't figured out why this happens. I think I ended up using a work-around that I didn't fully understand ... :( – Matt Fenwick May 28 '14 at 13:06
  • @alecxe I honestly don't know what I did ... hopefully I'll figure it out again at some point. – Matt Fenwick Jun 05 '14 at 17:09

1 Answers1

3

Quick solution is to remove __init__.py from the top level directory. Another option is to use relative imports, for your example: replace import a.b with from ...a import b.

The culprit of this mess and trickiness is nose importer.

If the directory you are running nosetests in, is a package, nose won't add it to sys.path, otherwise, it'll add it (source). Then, it goes up throw directory tree and applies recursively the same logic. Same thing for all affected files. This explains why it isn't working with __init__.py - root dir (src2 in your case) wasn't in sys.path - that's why package a wasn't found.

But, the open question here is: why it worked the first time, with src folder? src folder is on sys.path in this case. May be there will be other answers or edits.

See related questions:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • If I run nosetests from setup.py with setup.py nosetests, I'm getting this trouble from build/lib; build/lib/xxx has an __init__.py, and submodules of it don't work. – bmargulies Oct 21 '14 at 12:41