PytestCollectionWarning是pytest因测试类含__init__构造函数而跳过收集的警告,导致“collected 0 items”;需移除__init__,改用setup_class、fixture等生命周期钩子。

PytestCollectionWarning 是什么
它不是错误,但代表 pytest 根本没把你的类当测试用例收集进来。典型现象是:collected 0 items,或者运行后提示 cannot collect test class 'TestXxx' because it has a __init__ constructor。这意味着你写了 class TestXxx:,但 pytest 拒绝加载它——哪怕里面真有 def test_something():。
为什么 pytest 不收带 __init__ 的测试类
pytest 的测试类必须是“纯容器”,不能自己管理实例状态。一旦你写 def __init__(self),pytest 就认为你在试图手动控制实例生命周期,和它的 fixture + setup/teardown 机制冲突。
- 类里直接定义
__init__→ 触发警告,整个类被跳过 - 继承的父类(比如 POM 页面类、BaseTest 类)里有
__init__→ 同样触发警告,哪怕子类没写 - 甚至
__new__或某些元编程操作也会导致类似问题(比如用Enum命名以Test开头的类)
怎么改才不报这个警告
去掉所有测试类及其父类中的 __init__,改用 pytest 原生生命周期钩子:
- 需要模块级初始化?写
def setup_module():和def teardown_module(): - 需要类级准备?在测试类里加
def setup_class(self):(注意:没__init__才能生效) - 需要每个测试方法前重置?用
def setup_method(self): - 要传参或复用对象?全靠
@pytest.fixture,别在类里存实例变量
示例:把 __init__ 里初始化 driver 的逻辑,挪到 setup_class 或 fixture 里:
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
立即学习“Python免费学习笔记(深入)”;
class TestLogin:
def setup_class(self):
self.driver = webdriver.Chrome() # ✅ 可以
<pre class="brush:php;toolbar:false;">def teardown_class(self):
self.driver.quit()
def test_login_success(self):
self.driver.get("https://example.com")
其他容易被忽略的触发点
这个警告不只盯 __init__,还有几个隐蔽来源:
- 文件名或类名含中文、空格、特殊字符,导致 pytest 解析失败
- 测试类继承了带
__init__的非测试基类(比如你封装了一个BaseApi类,它有构造函数) - 用了
@pytest.mark.xxx但没在pytest.ini里注册,先报PytestUnknownMarkWarning,再连带影响收集逻辑 - Python 版本升级后,某些第三方库内部触发
DeprecationWarning,而 pytest 默认把部分警告转成 collection 阶段异常
真正麻烦的从来不是警告本身,而是它背后暴露的测试组织方式问题:把 pytest 当 unittest 用,却没理解它对“无状态类”的强约束。

















