问题描述
对于此(固定的)unittest.TestCase布局:
For this (fixed) unittest.TestCase layout:
#!/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
的框架中使用.预期和实际产量:
This works using stdlib
's framework. Expected and actual output:
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
但是,由于我实际上是在使用鼻子,因此,这种技巧似乎不同意.我得到的输出是:
However, since I am actually using nose, this trick seems to not agree with it. The output I got is:
C:\Users\santa4nt\Desktop>C:\Python27\python.exe C:\Python27\Scripts\nosetests test_meta.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
简而言之,由元类生成的test_*
方法不会向注册鼻子.谁能阐明这一点?
In short, the test_*
methods generated by the metaclass do not register with nose. Can anyone shed a light on this?
谢谢
推荐答案
因此,在侦查了stdlib的unittest
以及鼻子的加载器和选择器源代码之后,事实证明鼻子可以覆盖unittest.TestLoader.getTestCaseNames
来使用自己的选择器(带有插件点).
So, after sleuthing through both stdlib's unittest
and nose's loader and selector source code, it turns out that nose overrides unittest.TestLoader.getTestCaseNames
to use its own selector (with plugin points).
现在,鼻子的选择器会寻找一种潜在方法的method.__name__
来匹配某些正则表达式,黑白列表以及插件的决定.
Now, nose's selector looks for a potential method's method.__name__
to match certain regexes, black and white lists, and plugins' decisions.
就我而言,动态生成的函数具有其testable.__name__ == '<lambda>'
,与鼻子的选择器条件都不匹配.
In my case, the dynamically generated functions have its testable.__name__ == '<lambda>'
, matching none of nose's selector criteria.
要修复,
# 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
这篇关于鼻子,unittest.TestCase和元类:未发现自动生成的test_ *方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!