2011-03-03 49 views
12

这是unittest and metaclass: automatic test_* method generation后续问题:鼻子,和unittest.TestCase生成元类:自动生成TEST_ *方法没有发现

对于这种(固定的)布局unittest.TestCase生成:

#!/usr/bin/env python 

import unittest 


class TestMaker(type): 

    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}_v4,6(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) 
       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() 

这使用stdlib的框架。预期和实际输出:,

C:\Users\santa4nt\Desktop>C:\Python27\python.exe test_meta.py 
Hello from __main__.TestCase.test_normal 
.[__main__.TestCase.test_that_false] that: False 
.[__main__.TestCase.test_that_true] that: True 
.[__main__.TestCase.test_this_false] this: False 
.[__main__.TestCase.test_this_true] this: True 
. 
---------------------------------------------------------------------- 
Ran 5 tests in 0.015s 

OK 

但是因为我实际使用nose,这一招似乎不同意。我得到的输出是:

C:\Users\santa4nt\Desktop>C:\Python27\python.exe C:\Python27\Scripts\nosetests test_meta.py 
. 
---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

OK 

总之,由元类产生的test_*方法不nose注册。任何人都可以阐明这一点吗?

感谢,

+0

看一看http://ivory.idyll.org/articles/nose-intro.html#a-somewhat-更完整的引导到测试发现,和执行。使用'-vv'运行可能会提供您所需的信息。 – ncoghlan 2011-03-03 04:38:32

+0

也看看http://stackoverflow.com/questions/347574/how-do-i-get-nose-to-discover-dynamically-generated-testcases – ncoghlan 2011-03-03 04:40:19

+0

那么,你知道什么,有人试图做类似的事情。我已经看过鼻子的测试生成器,但不幸的是,它不支持从'unittest.TestCase'派生的测试类,我需要在其子类树中定义的fixtures。 – Santa 2011-03-03 05:15:22

回答

17

因此,通过两个STDLIB的unittest和鼻子的装载机选择源代码侦探后,事实证明,鼻子覆盖unittest.TestLoader.getTestCaseNames使用它自己的选择(与插件点)。

现在,鼻子的选择器寻找一个潜在的方法method.__name__来匹配某些正则表达式,黑名单和插件的决定。

在我的情况下,动态生成的函数有它的testable.__name__ == '<lambda>',匹配任何鼻子的选择器标准。

要解决,

 # inject methods: test{testname}_v4,6(self) 
     for suffix, arg in (('_false', False), ('_true', True)): 
      testable_name = 'test{0}{1}'.format(testname, suffix) 
      testable = lambda self, arg=arg: meth(self, arg) 
      testable.__name__ = testable_name # XXX: the fix 
      attrs[testable_name] = testable 

千真万确:

(sandbox-2.7)bash-3.2$ nosetests -vv 
test_normal (test_testgen.TestCase) ... ok 
test_that_false (test_testgen.TestCase) ... ok 
test_that_true (test_testgen.TestCase) ... ok 
test_this_false (test_testgen.TestCase) ... ok 
test_this_true (test_testgen.TestCase) ... ok 

---------------------------------------------------------------------- 
Ran 5 tests in 0.005s 

OK