Was introduced to an interesting problem today when decorating tests that need to be discovered by the nose runner. By default, nose explores a directory looking for things named
tests and then executes those functions, classes, modules, etc. as tests. A standard test suite for me looks something like:
import unittest class MyTests(unittest.TestCase): def test_undecorated(self): """ assert undecorated works """ self.assertEqual(2+2, 4)
The problem came up when we wanted to decorate a test with some extra functionality, for example loading a fixture:
def load_fixture(func): def wrapper(*args, **kwargs): # Load a fixture return func(*args, **kwargs) return wrapper class MyTests(unittest.TestCase): @load_fixture def test_decorated(self): """ assert a decorated test works """ self.assertEqual(2+2, 4)
The key to remember is that you must wrap the function so that the name and docstring are added to the internal wrapper, thus allowing the nose test discovery function to work:
from functools import wraps def load_fixture(func): @wraps(func) def wrapper(*args, **kwargs): # Load a fixture return func(*args, **kwargs) return wrapper
Thanks to @ndanielsen for pointing this out, it’s going to save me a bit of trouble in the future, I expect.