Nose 不会静态扫描测试,因此您可以使用元类魔法来制作 Nose 找到的测试。
困难的部分是标准元类技术没有正确设置 func_name 属性,这是 Nose 在检查类上的方法是否为测试时所寻找的。p>
这是一个简单的元类。它查看 func dict 并为它找到的每个方法添加一个新方法,断言它找到的方法有一个文档字符串。这些新的合成方法被命名为"test_%d" %i。
import new
from inspect import isfunction, getdoc
class Meta(type):
def __new__(cls, name, bases, dct):
newdct = dct.copy()
for i, (k, v) in enumerate(filter(lambda e: isfunction(e[1]), dct.items())):
def m(self, func):
assert getdoc(func) is not None
fname = 'test_%d' % i
newdct[fname] = new.function(m.func_code, globals(), fname,
(v,), m.func_closure)
return super(Meta, cls).__new__(cls, 'Test_'+name, bases, newdct)
现在,让我们创建一个使用这个元类的新类
class Foo(object):
__metaclass__ = Meta
def greeter(self):
"sdf"
print 'Hello World'
def greeter_no_docstring(self):
pass
在运行时,Foo 实际上将被命名为Test_Foo,并将有greeter、greeter_no_docstring、test_1 和test_2 作为其方法。当我在这个文件上运行nosetests 时,输出如下:
$ nosetests -v test.py
test.Test_Foo.test_0 ... FAIL
test.Test_Foo.test_1 ... ok
======================================================================
FAIL: test.Test_Foo.test_0
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/Users/rmcgibbo/Desktop/test.py", line 10, in m
assert getdoc(func) is not None
AssertionError
----------------------------------------------------------------------
Ran 2 tests in 0.002s
FAILED (failures=1)
这个元类并没有真正有用,但是如果你使用Meta 不是一个适当的元类,而是更多的功能元类(即,将一个类作为参数并返回一个新类,一个重命名以便鼻子会找到它),那么它是有用的。作为鼻子测试套件的一部分,我已经使用这种方法自动测试文档字符串是否符合 Numpy 标准。
另外,我在使用 new.function 正确关闭时遇到了很多麻烦,这就是为什么这段代码使用 m(self, func) ,其中 func 被设为默认参数。在value 上使用闭包会更自然,但这似乎不起作用。