您的位置:首页 > 编程语言 > Python开发

Python unittest 参数化测试

2014-08-05 23:56 429 查看
最近在用Python自带的unittest框架做测试,但发现此包不支持类似JUnit那样的参数化测试功能。下面给出一简单实现,就是效率和代码美观程度差了点:)

约定

参数化case的名字必须以 "parameterized_" 为前缀,后面跟真正的test名字;数据提供函数必须是classmethod,以 "collection_" 为前缀,后面跟真正的test名字。

比如 parameterized_test_add 和 collection_test_add 就是一组参数化case,其中testcase基础名字为test_add,参数化后具体的case为test_add_0, test_add_1, test_add_2 等等。关于parameterized_test_add 和 collection_test_add 的格式见下文。为实现此功能,必须重载unittest的 TestCase 和 TestLoader。

重载unittest.TestCase

class Test(unittest.TestCase):

def __init__(self, methodName='runTest'):
def isParameterizedMethod(attrname):
return attrname.startswith("parameterized") 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,7,9]

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)


输出如下:

D:\workspace>test.py
1
.4
.9
.25
.49
.81
.
----------------------------------------------------------------------
Ran 6 tests in 0.010s

OK
<unittest.runner.TextTestResult run=6 errors=0 failures=0>


在该用例中,真正的testcase定义在test_body函数中。collection_test_add 必须是一个无参的classmethod,返回一个list;parameterized_test_add 必须为非 classmethod 的成员函数,接受一个入参,该入参为 collection_test_add 所返回的 list 的元素,显然,该 list 的元素可以是任意数据类型,可以是list,tuple,dict等等,这样在test_body内可以接收更加丰富的输入。

本例中,collection_test_add 所返回的 list 中有6个元素,依次生成 test_add_0, test_add_1, test_add_2, test_add_3, test_add_4, test_add_5 共六个具体的case。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: