0

Summary: Using PyDev, I can't get one Python module (FooTest) to import another (FooMock) in the same (test) source folder.

I have two source folders and four Python modules, with the directory structure below. The minimal example code is at the end of the question. Although I have provided a lot of information, please don't let this intimidate you - it's a simple problem scenario.

PyDevProject/
  src/         (source folder for prod code)
    foo/
      __init__.py
      Bar.py
      Foo.py
  test/        (source folder for tests)
    foo/
      __init__.py
      FooMock.py
      FooTest.py

The issue here is that when I attempt to import FooMock class in the FooTest module, I get the following error (running PyUnit to run the FooTest tests):

Finding files... done.
Importing test modules ... Traceback (most recent call last):
  File "/Applications/Eclipse.app/Contents/Eclipse/plugins/org.python.pydev_4.5.4.201601292234/pysrc/_pydev_runfiles/pydev_runfiles.py", line 468, in __get_module_from_str
mod = __import__(modname)
  File "/Users/me/Development/krtiWorkspace/ImportTest/test/foo/FooTest.py", line 4, in <module>
    from foo.FooMock import FooMock
ImportError: No module named FooMock
ERROR: Module: FooTest could not be imported (file: /Users/me/Development/krtiWorkspace/ImportTest/test/foo/FooTest.py).
done.

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

Things I've tried:

  • Even though FooMock and FooTest are both in the same Python package, FooMock can't be imported.
  • Moving FooMock to under the src/ directory works, even if placed under a unique Python package (as long as it's under src/). But this isn't acceptable for me (to have test code in production source folders).
  • I've ensured the PYTHONPATH settings in PyDev are set to specify both folders are source folders.
  • Copying and pasting the FooMock code into the FooTest code works. But this isn't acceptable for me (since I'd like to reference FooMock elsewhere, in multiple test files and I don't want multiple copies of FooMock floating around consequently).

Is there anything I can do about this?

Code:

# Code for Bar.py -----------------------------------------------------
class Bar(object):
    def __init__(self, foo):
        self.foo = foo
    def next(self):
        self.foo.incr()

# Code for Foo.py -----------------------------------------------------
class Foo(object):
    def __init__(self):
        self.num = 0
    def incr(self):
        self.num = self.num + 1

# Code for FooMock.py -------------------------------------------------
class FooMock(object):
    def mock_incr(self):
        self.hit = True

# Code for FooTest.py -------------------------------------------------
import unittest
from foo.Foo import Foo
from foo.Bar import Bar
from foo.FooMock import FooMock

class Test(unittest.TestCase):
    def test_Foo(self):
        foo = Foo()
        foo.incr()
        self.assertEquals(1, foo.num, "should be 1")
    def test_Bar(self):
        foo = FooMock()
        bar = Bar(foo)
        bar.next()

if __name__ == "__main__":
    unittest.main()

Screenshot of directory: Image showing directory structure and PYTHONPATH as previously explained

Ahmed Tawfik
  • 1,159
  • 1
  • 8
  • 13

1 Answers1

0

You have a module named foo in your PYTHONPATH twice. In the first directory, where the package foo is found, there is indeed no module named FooMock.

Can you rename the module foo under the test source directory to something else? Like footests instead of foo?

grepe
  • 1,897
  • 2
  • 14
  • 24
  • That was the issue! Here I was assuming this was like Java. Rookie mistake. Thanks @grepe. To confirm, renaming the test/foo package to test/footest enabled Python to find FooMock. – Ahmed Tawfik May 01 '16 at 20:01
  • A small extension to my question: do all Python packages have to be unique? I.e. Can I have SRC/foo.bar and TEST/tests.foo.bar? I'm checking now in any case. – Ahmed Tawfik May 01 '16 at 22:31
  • you can extend the package once you've imported it in your code (this is referred to as "monkey patching", see this SO topic for example: http://stackoverflow.com/questions/5626193/what-is-a-monkey-patch). but the way import works is that it looks for the package in each of the directories included in your PYTHONPATH in order and once it finds it, it stops there. so if the package is in the path multiple times, it is included only the first time and only the code from this first definition is used. – grepe May 02 '16 at 08:08
  • I think this is more relevant to my issue: http://stackoverflow.com/questions/9207748/unit-testing-entire-project-hierarchy-in-python-using-unittest-in-pydev In any case, thanks again, @grepe – Ahmed Tawfik May 02 '16 at 09:59