鼻子,unittest.TestCase 和元类:未发现自动生成的 test_* 方法
Posted
技术标签:
【中文标题】鼻子,unittest.TestCase 和元类:未发现自动生成的 test_* 方法【英文标题】:nose, unittest.TestCase and metaclass: auto-generated test_* methods not discovered 【发布时间】:2011-07-07 18:40:27 【问题描述】:这是unittest and metaclass: automatic test_* method generation的后续问题:
对于这个(固定的)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: testtestname_v4,6(self)
for suffix, arg in (('_false', False), ('_true', True)):
testable_name = 'test01'.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 注册。任何人都可以对此有所了解吗?
谢谢,
【问题讨论】:
看看ivory.idyll.org/articles/…。使用-vv
运行可能会为您提供所需的信息。
也看***.com/questions/347574/…
嗯,你知道吗,有人试图做类似的事情。不过,我查看了鼻子的测试生成器,但不幸的是它不支持从 unittest.TestCase
派生的测试类,我需要在其子类树中定义的固定装置。
@Santa 非常感谢!!一个非常有用的例子。
【参考方案1】:
因此,在通过 stdlib 的 unittest
和 nose 的加载器和选择器源代码进行侦查之后,事实证明,nose 会覆盖 unittest.TestLoader.getTestCaseNames
以使用自己的选择器(带有插件点)。
现在,nose 的选择器查找潜在方法的 method.__name__
以匹配某些正则表达式、黑白列表和插件的决定。
在我的例子中,动态生成的函数有它的testable.__name__ == '<lambda>'
,不匹配鼻子的选择器标准。
修复,
# inject methods: testtestname_v4,6(self)
for suffix, arg in (('_false', False), ('_true', True)):
testable_name = 'test01'.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_* 方法的主要内容,如果未能解决你的问题,请参考以下文章
django.test.TestCase vs unittest vs django.utils.unittest.TestCase 之间的区别