Alex Harvey
Alex Harvey

Reputation: 15502

Unable to import a class in unittest

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

Answers (2)

Ridge Kimani
Ridge Kimani

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

Chen A.
Chen A.

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

Related Questions