这是我的previous question的后续行动。如何获取鼻子来发现动态生成的测试用例?
在前面的问题中,我们探索了一些方法来实现对整个函数族进行基本相同的测试,以确保测试不会停在第一个失败的函数上。
我的首选解决方案使用元类来动态地将测试插入unittest.TestCase。不幸的是,由于鼻子静态扫描测试用例,所以鼻子不会选择它。
如何获得鼻子来发现并运行这样的TestCase?有关TestCase的示例,请参阅here。
这是我的previous question的后续行动。如何获取鼻子来发现动态生成的测试用例?
在前面的问题中,我们探索了一些方法来实现对整个函数族进行基本相同的测试,以确保测试不会停在第一个失败的函数上。
我的首选解决方案使用元类来动态地将测试插入unittest.TestCase。不幸的是,由于鼻子静态扫描测试用例,所以鼻子不会选择它。
如何获得鼻子来发现并运行这样的TestCase?有关TestCase的示例,请参阅here。
鼻子有这样的东西“测试发电机”功能。你编写一个生成器函数,生成你想运行它的每个“测试用例”函数以及它的参数。继以前的例子,这可以检查每个功能在一个单独的测试:
import unittest
import numpy
from somewhere import the_functions
def test_matrix_functions():
for function in the_functions:
yield check_matrix_function, function
def check_matrix_function(function)
matrix1 = numpy.ones((5,10))
matrix2 = numpy.identity(5)
output = function(matrix1, matrix2)
assert matrix1.shape == output.shape, \
"%s produces output of the wrong shape" % str(function)
你可以尝试生成测试用例类与类型()
class UnderTest_MixIn(object):
def f1(self, i):
return i + 1
def f2(self, i):
return i + 2
SomeDynamicTestcase = type(
"SomeDynamicTestcase",
(UnderTest_MixIn, unittest.TestCase),
{"even_more_dynamic":"attributes .."}
)
# or even:
name = 'SomeDynamicTestcase'
globals()[name] = type(
name,
(UnderTest_MixIn, unittest.TestCase),
{"even_more_dynamic":"attributes .."}
)
当鼻子试图导入test_module所以它应该工作这应该被创建。
这种方法的优点是可以动态创建多个测试组合。
鼻子不扫描测试静态,这样你就可以使用元类魔法使测试,鼻子找到。
难题在于标准元类技术不能正确设置func_name属性,这是鼻子在检查类中的方法是否为测试时寻找的内容。
这是一个简单的元类。它通过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标准,作为鼻子测试套件的一部分。
此外,我有很多麻烦得到适当的封闭与新的工作。函数,这就是为什么此代码使用m(self, func)
其中func
被设置为默认参数。使用value
以上的封闭会更自然,但这似乎不起作用。
你试过我的解决方案吗?它不是基于任何魔法,所产生的套件应该是可以发现的。 – muhuk 2008-12-07 15:50:19