Reputation: 15502
This is probably a beginner question but I'm really pulling my hair out.
I have a very simple Python script "foo":
#!/usr/bin/env python
class Foo():
def __init__(self):
self.do_something()
def do_something(self):
print "foo"
def main():
Foo()
if __name__ == '__main__':
main()
Script works fine:
$ python foo.py
foo
I want to test the function "do_something" in unittest and I have this code:
#!/usr/bin/env python
import unittest
import foo
from foo import *
class TestFoo(unittest.TestCase):
def test_foo(self):
Foo()
def main():
unittest.main()
if __name__ == "__main__":
main()
If I run the tests, however, I get:
$ python pyunit/foo.py
E
======================================================================
ERROR: test_foo (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
File "pyunit/foo.py", line 9, in test_foo
Foo()
NameError: global name 'Foo' is not defined
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
My project structure:
$ tree
.
├── foo.py
└── pyunit
└── foo.py
I have been playing around with inspect
, dir()
, the Python debugger etc but I'm getting nowhere.
Although import foo
and from foo import *
both execute fine, and I see the function main
imported from that file, the class itself Foo
doesn't seem to be imported.
My objective, ultimately, is to then write unit tests for the functions in the class Foo
.
What am I doing wrong?
Upvotes: 1
Views: 5712
Reputation: 11
Python tests can be disturbing especially with relative imports. So I got a work around.
First and Foremost: I suggest you install pytest which resolves the name in the sys.path that the test module is contained.. Install it by running pip install pytest
.
For the relative import, you are trying to access the module outside the test package, to resolve this use the dot representation of imports, that is
from ..foo import Foo
Make sure you have removed import foo
Then try running the test pytest
or pytest test_foo.py
(if you are inside the pyunit folder)
Upvotes: 1
Reputation: 11328
You shouldn't use the same file name (foo.py) in your module. Change your test module to test_foo instead. Explicit is better than implicit.
When importing a module from a parent directory, you need to use from <parent_dir> import <module_name>
, so in your case you should state from <parent_dir> import foo
You encounter the ImportError: No module named foo
error becuase your module is not part of your sys.path
.
Simplest way to import your local directory to python's lookup path:
import sys
sys.path.append('.')
Before the other import statements. This will append the project dir to the path. If you have multiple classes with the same name, you better use sys.path.insert(0, '.')
to push the path into the first position
Upvotes: 3