Ulrich Eckhardt wrote: > Hi! > > I'm having problems using a metaclass to generate test functions. This > works when I try to run all tests from the module or test case, but it > fails when I'm trying to specify a single test function. My environment > is Python 2.7.3 on MS Windows 7 at the moment. It should be upgraded to > at least 2.7.4 or better to 3, but see the notes on Python 3 below. > > # my_module.py > import unittest > class X(unittest.TestCase): > def __metaclass__(name, bases, dict): > # attach function > def test(self): > pass > dict['test_1'] = test > dict['test_2'] = test > # create class > return type(name, bases, dict) > > The error when I'm trying to run "python -m unittest my_module.X.test_1" > is: "Value error: no such test method in <class 'my_module.X'>: test". > The astonishing part is that it claims that "test" is not found while I > asked it to run "test_1". The name it complains about is the name of the > function inside the metaclass function. In all other cases, like e.g. > giving "-v" it reports the correct function name. My question here is > whether I'm doing something wrong or whether I discovered a bug.
Here's a simpler demo of the problem: $ cat tmp.py import unittest class X(unittest.TestCase): def test_1(self): pass test_1.__name__ = "test_2" $ python -m unittest -v tmp test_1 (tmp.X) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK $ python -m unittest -v tmp.X.test_1 Traceback (most recent call last): File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main "__main__", fname, loader, pkg_name) File "/usr/lib/python2.7/runpy.py", line 72, in _run_code exec code in run_globals File "/usr/lib/python2.7/unittest/__main__.py", line 12, in <module> main(module=None) File "/usr/lib/python2.7/unittest/main.py", line 94, in __init__ self.parseArgs(argv) File "/usr/lib/python2.7/unittest/main.py", line 149, in parseArgs self.createTests() File "/usr/lib/python2.7/unittest/main.py", line 158, in createTests self.module) File "/usr/lib/python2.7/unittest/loader.py", line 128, in loadTestsFromNames suites = [self.loadTestsFromName(name, module) for name in names] File "/usr/lib/python2.7/unittest/loader.py", line 109, in loadTestsFromName return self.suiteClass([parent(obj.__name__)]) File "/usr/lib/python2.7/unittest/case.py", line 191, in __init__ (self.__class__, methodName)) ValueError: no such test method in <class 'tmp.X'>: test_2 It looks like this particular invocation relies on class attribute and function __name__ being identical. Please file a bug report. > Now, concerning Python 3, it fails to detect any test case at all! My > guess is that the unittest library was changed to use metaclasses itself > in order to detect classes derived from unittest.TestCase. Therefore, > overriding the metaclass breaks test case discovery. My question in that > context is how do I extend metaclasses instead of overriding it? In > other words, what is the equivalent to super() for class creation? Python 3 does not recognize the __metaclass__ attribute as the metaclass. You need to provide it like so: def __metaclass__(name, bases, dict): ... class X(unittest.TestCase, metaclass=__metaclass__): pass -- http://mail.python.org/mailman/listinfo/python-list