约定
参数化case的名字必须以 "param_" 为前缀,后面跟真正的test名字;数据提供函数必须是classmethod,以 "collection_" 为前缀,后面跟真正的test名字。
比如 parameterized_test_add 和 collection_test_add 就是一组参数化case,其中testcase基础名字为test_add,参数化后具体的case为test_add_0, test_add_1, test_add_2 等等。为实现此功能,必须重载unittest的 TestCase 和 TestLoader。
class Test(unittest.TestCase): def __init__(self, methodName='runTest'): def isParameterizedMethod(attrname): return attrname.startswith("param") and \ hasattr(getattr(self, attrname), '__call__') testFnNames = filter(isParameterizedMethod, dir(self)) for func in testFnNames: name = func.split("_", 1)[1] collect = "collection_" + name if hasattr(getattr(self, collect), '__call__'): collectFunc = getattr(self, collect) array = collectFunc() for index in xrange(len(array)): test = "%s_%d" % (name, index) setattr(self.__class__, test, getattr(self, func)(array[index])) # must called at last unittest.TestCase.__init__(self, methodName)
重载unittest.TestLoader
class Loader(unittest.TestLoader):
def getTestCaseNames(self, testCaseClass):
"""Return a sorted sequence of method names found within testCaseClass
"""
testFnNames = unittest.TestLoader.getTestCaseNames(self, testCaseClass)
def isParameterizedMethod(attrname, testCaseClass=testCaseClass,
prefix="parameterized"):
return attrname.startswith(prefix) and \
hasattr(getattr(testCaseClass, attrname), '__call__')
testFnNames0 = filter(isParameterizedMethod, dir(testCaseClass))
for func in testFnNames0:
name = func.split("_", 1)[1]
collect = "collection_" + name
if hasattr(getattr(testCaseClass, collect), '__call__'):
collectFunc = getattr(testCaseClass, collect)
for item in xrange(len(collectFunc())):
testFnNames.append("%s_%d" % (name, item))
if self.sortTestMethodsUsing:
testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
return testFnNames
编写测试用例
from unittest import * from Test import * from Loader import * class TestFunctions(Test): @classmethod def collection_test_add(cls): return [1,2,3,5] def parameterized_test_add(self, x): def test_body(self): print(x * x) return test_body if __name__ == '__main__': suite = Loader().loadTestsFromTestCase(TestFunctions) runner = unittest.TextTestRunner() rc = runner.run(suite) print(rc)
在该用例中,真正的testcase定义在test_body函数中。collection_test_add 必须是一个无参的classmethod,返回一个list;parame_test_add 必须为非 classmethod 的成员函数,接受一个入参,该入参为 collection_test_add 所返回的 list 的元素,显然,该 list 的元素可以是任意数据类型,可以是list,tuple,dict等等,这样在test_body内可以接收更加丰富的输入。
本例中,collection_test_add 所返回的 list 中有4个元素,依次生成 test_add_0, test_add_1, test_add_2, test_add_3共4个具体的case。