Import path for unit tests

B

Ben Finney

Howdy all,

My practice when writing unit tests for a project is to make 'test/'
subdirectories for each directory containing modules I want to test.

project-foo/
+-- lib/
| +-- test/
+-- data/
+-- gui/
| +-- test/
+-- server/
+-- test/

This means that I need to use relative paths to import the subject
code into the unit test module.

import unittest

import sys
sys.path.append('..')
import foomodule

class Test_Foo(unittest.TestCase):
# ...

This works, so long as the foomodule is *not* in the path before the
appended '..' directory. When writing unit tests for a development
version of a package that is already installed at an older version in
the Python path, this fails: the unit tests are not importing the
development version of foomodule.

What is the common idiom here? I can conceive of several possible ways
to get around it, all of which seem hackish to some degree.
 
D

Duncan Booth

Ben said:
This works, so long as the foomodule is *not* in the path before the
appended '..' directory. When writing unit tests for a development
version of a package that is already installed at an older version in
the Python path, this fails: the unit tests are not importing the
development version of foomodule.

Why not just insert foomodule's directory in front of the other entries in
sys.path instead of at the end?
What is the common idiom here? I can conceive of several possible ways
to get around it, all of which seem hackish to some degree.

I don't know if it is the common idiom, but I tend to write:

TESTDIR = os.path.dirname(os.path.abspath(__file__))
PROJECTDIR = os.path.dirname(TESTDIR)
if not TESTDIR in sys.path:
sys.path.insert(1, TESTDIR)
if not PROJECTDIRDIR in sys.path:
sys.path.insert(1, PROJECTDIR)

That gets put in a framework.py file in the test directory. run_tests.py
(in the same folder) looks like:

import unittest, os, sys
if __name__ == '__main__':
execfile(os.path.join(sys.path[0], 'framework.py'))

if __name__=='__main__':
suite = unittest.TestSuite()
for testfile in os.listdir(TESTDIR):
if testfile.startswith('test_') and testfile.endswith('.py'):
testfile = os.path.splitext(testfile)[0]

module = __import__(testfile)
suite.addTest(module.suite())

unittest.TextTestRunner(verbosity=2).run(suite)

and all the test files import framework. That way I can run an individual
test_xxx.py, or use run_tests.py to run all test files, and I can start
them from the test directory, the project directory, or any other
directory.
 
B

Ben Finney

Duncan Booth said:
I don't know if it is the common idiom, but I tend to write:

TESTDIR = os.path.dirname(os.path.abspath(__file__))
PROJECTDIR = os.path.dirname(TESTDIR)
if not TESTDIR in sys.path:
sys.path.insert(1, TESTDIR)
if not PROJECTDIRDIR in sys.path:
sys.path.insert(1, PROJECTDIR)

Thankyou, that works better than what I was doing.

But it's my idea of "hackish" :) It works, and is comprehensible. But
it's pretty heavyweight for something I need to do all the time (i.e.
writing unit test modules for various projects).

Anyone else have a preferred way of doing this? Or will I have to wait
until PEP 328 is integrated?

<URL:http://www.python.org/peps/pep-0328.html>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,737
Latest member
Georgeengab

Latest Threads

Top