Skip to content

Instantly share code, notes, and snippets.

@santa4nt
Created March 3, 2011 03:17
Show Gist options
  • Save santa4nt/852268 to your computer and use it in GitHub Desktop.
Save santa4nt/852268 to your computer and use it in GitHub Desktop.
A metaclass to generate test_{name}_{[true,false]} methods from _test_{name}.
#!/usr/bin/env python
import unittest
class TestMaker(type):
"""For a class to assign its __metaclass__ to this type, the class
creation will look for methods that are prefixed with '_test{name}'.
The method is assumed to take two arguments (self and a boolean).
From that, two methods will be dynamically generated, with the names
'test_{name}_true' and 'test_{name}_false' with those respective
boolean arguments supplied.
"""
def __new__(cls, name, bases, attrs):
callables = dict([
(meth_name, meth) for (meth_name, meth) in attrs.items() if
meth_name.startswith('_test')
])
for meth_name, meth in callables.items():
assert callable(meth)
_, _, testname = meth_name.partition('_test')
# inject methods: test{testname}_{[true,false]}(self)
for suffix, arg in (('_false', False), ('_true', True)):
testable_name = 'test{0}{1}'.format(testname, suffix)
testable = lambda self, func=meth, arg=arg: func(self, arg)
# testable.__name__ == '<lambda>', invalidating nose's Selector.wantMethod
testable.__name__ = testable_name
attrs[testable_name] = testable
return type.__new__(cls, name, bases, attrs)
class TestCase(unittest.TestCase):
__metaclass__ = TestMaker
def test_normal(self):
print 'Hello from ' + self.id()
def _test_this(self, arg):
print '[{0}] this: {1}'.format(self.id(), str(arg))
def _test_that(self, arg):
print '[{0}] that: {1}'.format(self.id(), str(arg))
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment