tags:

views:

226

answers:

4

I don't do tests, but I'd like to start. I have some questions :

  1. Is it ok to use the unittest module for that? From what I understand, the unittest module will run any method starting with test.
  2. if I have a separate directory for the tests ( consider a directory named tests ), how would I import the code I'm testing? Do I need to use the imp module? Here's the directory structure :

src/

tests/

+4  A: 

It's fine to use unittest. This module will run methods beginning with test for classes which inherit from unittest.TestCase.

There's no need to use the imp module - your test module would just import the code under test as normal. You might need to add the src directory to your path:

import sys
sys.path.append('../src') # OnLinux  - use r'..\src' for Windows

This code would be in your test module(s) before any import of your modules.

A better approach is to use the OS environment variable PYTHONPATH.

(Windows) SET PYTHONPATH=path\to\module; python test.py

(Linux) PYTHONPATH=path/to/module; python test.py

An alternative to unittest is nose.

Vinay Sajip
Don't mess with `sys.path.append()`. Use PYTHONPATH, it's much, much simpler.
S.Lott
I think you meant sys.path there.
Geo
How should PYTHONPATH be used?
Geo
+2  A: 

I had a bit of problem with the whole seperate directory for tests issue.

The way I solved it was by having a test runner in the source directory with the following code:

import sys, os, re, unittest

# Run all tests in t/

def regressionTest():
    path = os.path.abspath(os.path.dirname(sys.argv[0])) + '/t'
    files = os.listdir(path)
    test = re.compile("^t_.+\.py$", re.IGNORECASE)
    files = filter(test.search, files)
    filenameToModuleName = lambda f: 't.'+os.path.splitext(f)[0]
    moduleNames = map(filenameToModuleName, files)
    modules = map(__import__, moduleNames)
    modules = map(lambda name: sys.modules[name], moduleNames)
    load = unittest.defaultTestLoader.loadTestsFromModule
    return unittest.TestSuite(map(load, modules))

suite = regressionTest()

if __name__ == "__main__":
    unittest.TextTestRunner(verbosity=2).run(suite)

Then I had a folder named t containing all my tests, named t_<something>.py.

If you need help on getting started with unit testing in Python, I can recommend the official documentation and Dive Into Python among other things.

Sebastian P.
+5  A: 

Another good way to start tests with your Python code is use the doctest module, whereby you include tests inside method and class comments. The neat bit is that these serve as code examples, and therefore, partial documentation. Extremely easy to do, too.

Dave
+1  A: 

As mentioned by Sebastian P., Mark Pilgrim's Dive Into Python has great chapters on unit testing and test-driven development using Python's unittest module. I used these chapters to get started with testing, myself.

I wrote a blog post describing my approach to importing modules for testing. Note that it solves the shortcoming of Vinay Sajip's approach, which will not work if you call the testing module from anywhere but the directory in which it resides. A reader posted a nice solution in the comments of my blog post as well.

S. Lott hints at a method using PYTHONPATH in Vinay's post; I hope he will expound on it.

gotgenes