如何避免pytest实例化测试用例的父类(Template Method Pattern场景)
如何避免pytest实例化测试用例的父类(Template Method Pattern场景)
哈哈,这个场景我太熟了!之前用模板方法模式写测试用例的时候也踩过一模一样的坑,给你几个亲测有效的解决方案:
方案一:父类禁用测试标记,子类显式开启
你之前只给父类设了__test__ = False,但子类会继承这个属性,所以连子类的测试也被一起禁用了。只要在每个子类里重新把__test__设为True就搞定了:
import unittest class Parent(unittest.TestCase): __test__ = False # 告诉pytest:这个类只是模板,不是可执行的测试类 # 这里是所有子类共享的测试逻辑 def test_common_behavior(self): self.assertGreater(self.get_test_value(), 0) # 留给子类实现的“抽象”方法(不用abc模块,避免实例化报错) def get_test_value(self): raise NotImplementedError("子类必须实现这个方法") class Child1(Parent): __test__ = True # 显式开启子类的测试功能 def get_test_value(self): return 6 class Child2(Parent): __test__ = True def get_test_value(self): return 12
这样pytest会正常执行Child1、Child2的所有继承测试,完全不会去碰Parent类的测试项,完美符合你的需求。
方案二:用pytest钩子自动过滤父类测试
如果不想给每个子类都加__test__ = True,可以在项目根目录的conftest.py里加个收集测试用例的钩子函数,自动跳过父类的测试:
import pytest # 替换成你的父类所在的实际模块路径 from your_test_module import Parent def pytest_collection_modifyitems(items): for item in items: # 检查当前测试项是否属于父类本身 if item.cls is Parent: item.add_marker(pytest.mark.skip(reason="父类是模板类,无需执行测试"))
这个方法的好处是子类完全不用做任何修改,钩子会自动识别并跳过父类的所有测试用例,子类继承的测试逻辑不受任何影响。
方案三:测试方法内判断跳过(适合测试少的场景)
如果你的父类只有少数几个测试方法,也可以在每个测试方法里加个简单判断,直接跳过父类自身的执行:
class Parent(unittest.TestCase): def test_common_behavior(self): # 如果当前实例是父类本身,直接跳过 if self.__class__ is Parent: self.skipTest("仅子类执行此测试,父类跳过") # 这里是测试逻辑 self.assertGreater(self.get_test_value(), 0)
这个方法不需要改任何配置,也不用给子类加属性,就是每个测试方法都要加这段判断,适合测试方法不多的情况。
补充:你之前尝试的方法为什么不行
- 把父类设为抽象类:pytest在收集测试用例时会尝试实例化父类,而抽象基类(比如用
abc.ABC)无法被实例化,所以会直接标记为失败,确实不适合和unittest.TestCase搭配用在pytest里。 - 只给父类设
__test__ = False:因为Python的属性继承机制,子类会继承这个__test__属性,导致子类的测试也被一并禁用,必须在子类里显式覆盖开启。
备注:内容来源于stack exchange,提问作者DarkTrick
相关产品推荐
相关产品推荐

