unittest浅析,通过元类实现按书写顺序执行单元测试函数 utx,一个基于unittest的功能很多的测试用代码库 metaclass的用法
为了实现按书写顺序执行单元测试函数,找了一些资料,最后实现了这个功能,代码如下:
import unittest
from unittest import TestLoader
from fnmatch import fnmatchcase
class UnittestMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs["attrs_by_writing_order"] = list(attrs.keys())
return super().__new__(cls, name, bases, attrs)
class OrderedTestLoader(TestLoader):
"""This TestLoader will load testFnNames in the code writing order"""
def getTestCaseNames(self, testCaseClass):
"""Return a sorted sequence of method names found within testCaseClass
"""
def shouldIncludeMethod(attrname):
if not attrname.startswith(self.testMethodPrefix):
return False
testFunc = getattr(testCaseClass, attrname)
if not callable(testFunc):
return False
fullName = f'%s.%s.%s' % (
testCaseClass.__module__, testCaseClass.__qualname__, attrname
)
return self.testNamePatterns is None or \
any(fnmatchcase(fullName, pattern) for pattern in self.testNamePatterns)
testFnNames = list(filter(shouldIncludeMethod, testCaseClass.attrs_by_writing_order))
return testFnNames
class TestDemo(unittest.TestCase, metaclass=UnittestMetaclass):
r"""Author: zhang.haojian
本测试类的测试结果为".FF..E.","."表示测试通过,"F"表示不通过,"E"表示在执行测试函数时发生了并非由assert*系列函数引发的异常
测试结果的输出顺序是按函数名的字母序,与代码中的函数声明顺序不一定一致
形如FAIL: 测试函数名 (测试类名) 的是一个测试函数不通过时的提示行,下接断言异常信息,请核对代码并修改至测试通过之后再提交
如果所有样例都通过,最后会输出"OK",否则会输出FAILED (failures=2, errors=1)的字眼,告诉用户有几个样例failure了,有几个样例error了
"""
def setUp(self):
pass
def tearDown(self):
pass
def test_equal(self):
s = "this is a demo function"
self.assertEqual(s, "this is a demo function")
def test_equal2(self):
s = "this is another demo function"
self.assertEqual(s, "this is a demo function")
def test_in(self):
l = ["a", "b"]
self.assertIn("c", l)
def test_isinstance(self):
s = "I am a string"
self.assertIsInstance(s, str)
def test_bool(self):
d = {"a": "ABC"}
self.assertTrue(d["a"].isupper())
def test_error(self):
raise RuntimeError("a RuntimeError")
def test_assert_raise(self):
def change_tuple(t):
t[0] = 1
d = (1, 2)
self.assertRaises(TypeError, change_tuple, d)
self.assertRaisesRegex(TypeError, "'tuple' object does not support item assignment", change_tuple, d)
with self.assertRaisesRegex(TypeError, "'tuple' object does not support item assignment") as cm:
d[0] = 1
if __name__ == "__main__":
unittest.main(testLoader=OrderedTestLoader())
|