unittest 能自动发现并执行测试用例,规则如下:
- 首先指定要查找的目录(默认是当前目录)。
如果子目录属于 Python 包,则也加入查找范围。 - 然后在该目录下查找名称匹配
test*.py
的文件。 - 接着在该文件中查找继承
unittest.TestCase
的类, - 最后查找该类中名称以
test
开头的方法,作为测试用例来执行。
为了发现不是以 test
开头的测试方法,乃至更灵活地匹配,本文定义了一个继承 unittest.TestLoader
的子类。
代码
import sys
import unittest
import functools
from fnmatch import fnmatchcase
class MyTestLoader(unittest.TestLoader):
testNamePatterns = None
def getTestCaseNames(self, testCaseClass):
"""
Customize this code to allow you to filter test methods through testNamePatterns.
"""
def shouldIncludeMethod(attrname):
if not attrname.startswith(self.testMethodPrefix):
return False
testFunc = getattr(testCaseClass, attrname)
if not callable(testFunc):
return False
return self.testNamePatterns is None or \
any(fnmatchcase(attrname, pattern) for pattern in self.testNamePatterns)
testFnNames = list(filter(shouldIncludeMethod, dir(testCaseClass)))
if self.sortTestMethodsUsing:
testFnNames.sort(key=functools.cmp_to_key(self.sortTestMethodsUsing))
return testFnNames
if __name__ == '__main__':
testLoader = MyTestLoader()
testLoader.testMethodPrefix = ''
testLoader.testNamePatterns = ['test*', '*test'] # 查找以 test 开头或结尾的测试方法(注意这里是 shell 风格的通配符)
discovered_tests = testLoader.discover(start_dir='.', pattern='test*.py')
result = unittest.TextTestRunner(verbosity=2).run(discovered_tests)
sys.exit(0 if len(result.failures) + len(result.errors) == 0 else 1)
运行效果
[root@CentOS ~]# python3 runner.py
minus_test (test1.TestMath) ... FAIL
test_add (test1.TestMath) ... ok