VI.测试用例模块case.py
TestCase也是个神奇的类, 或者说是个蝙蝠类.既是哺乳动物又是鸟类
5.1 长得就是一只鸟
class TestCase(object): def __init__(self, methodName="runTest"): pass def addCleanup(self, typeobj, function): pass def doCleanups(self): pass # -----------测试用例fixture ---------------------- def setUP(sefl): pass def tearDown(self): pass # -----------测试用例fixture ---------------------- # -----------测试类fixture ---------------------- @classmethod def setUpClass(cls): pass @classmethod def tearDownClass(cls): pass # -----------测试类fixture ---------------------- def run(self, result): pass def __call__(self, *args, **kwargs): passView Code
TestCase从类结构看类似TestSuite, 也是一个测试套组织. 将类作用域下以test_开头的可调用模块聚合在TestCase类的namespace下, 或者说是类模块下.
同时, 他也有两对共享的fixture: 类级别的类夹具(setUpClass, tearDownClass)负责类内部的共享资源管理, 函数级别的夹具(setUp, tearDown)负责函数间的公
共资源管理&公有动作切片. 还有功能超级赞的临时资源栈管理神器(addSetupCleanup, addCleanup, doSetupCleanup, doCleanup).
AOP(Aspect Oriented Program)的感觉有木有?在测试用例执行前后, 在测试类执行前后, 在失败处理前后. 非常Python的操作.
5.2 带起娃来又是哺乳动物
TestCase从对象行为看只是一个测试用例(函数 & 类方法). TestCase没有按照套路实现__iter__方法将迭代和执行转交给各个函数, 而是自己亲自下场代理
了函数的行为.demo,
testCase = TestCase(methodName="test_upper") testCase.(result)
还是回到load模块, 最后导出函数的过程. load通过类模块, 反射到类中可执行的名称以test*开头的函数名称列表. 然后通过类TestCas的构造函数__init__方法
得到了可执行的函数对象. Trick就在这个TestCase的构造函数里面, 他没有像名字一样去实例化一组测试用例.而是通过函数名找到可调用的测试函数对象!
testMethod = getattr(self, methodName) self._testMethodName = methodName
寄存函数名, 校验存在这个函数之后.走了...
run函数的操作.run函数的主要目标是通过self._testMethodName找到测试函数对象并执行. 前置动作有检查skip属性, 如果发现类或者函数有skip属性, 则直接
抛异常continue本函数. 这里就涉及到case.py模块的skip装饰器, 直白的说这些装饰器就是给测试模块(类&函数)动态绑定__unittest__skip__ 属性. 这个属性作为测
试对象的hook从类定义的时候就预制了, 知道运行的时候才动态判定, 其实中间过程是存在可hack空间的. 比如子类的init函数, 或者load导入函数的重载, 可以利用
这个属性直接黑掉某个&某类型用例.
本文只叙述最简单例子的主逻辑, 其他的复杂场景和旁枝就不赘述了.