setup_module 在现代 pytest 中常不生效,因其需显式启用 unittest 兼容模式、仅限顶层定义、无法依赖 fixture 且易被 module/session fixture 覆盖;推荐用 autouse=True 的 module-scoped fixture 替代。

setup_module 在现代 pytest 中已不推荐使用,它属于 unittest 风格的遗留机制,且在 pytest 7.0+ 中与 pytest_configure、conftest.py 中的 fixture 冲突明显,容易导致初始化被跳过或执行多次。
为什么 setup_module 常常不生效?
pytest 默认不识别 setup_module 和 teardown_module,除非你显式启用旧式 unittest 兼容模式(通过 --tb=short --collect-only 等命令看不出问题,但运行时不会调用)。更关键的是:它只在模块顶层定义、且函数名严格为 setup_module 时才可能触发,但即便如此,也绕不开以下限制:
- 无法接收 fixture(比如
tmp_path、caplog),不能依赖 pytest 的依赖注入系统 - 不支持参数化测试的前置逻辑分离
- 若模块中存在
conftest.py定义的scope="session"或scope="module"fixture,setup_module可能被完全忽略 - 在 pytest-xdist 并行模式下行为未定义,极大概率不执行
替代方案:用 module-scoped fixture 替代 setup_module
这才是 pytest 原生、稳定、可测试的模块级初始化方式。所有初始化逻辑应写在 conftest.py 中,而非测试文件里:
# conftest.py
import pytest
<p>@pytest.fixture(scope="module", autouse=True)
def init_database():</p><h1>模块首次加载时执行一次</h1><pre class="brush:php;toolbar:false;">print("→ 初始化数据库连接")
db = connect_to_test_db() # 你的初始化逻辑
yield db
# teardown 部分(模块所有测试跑完后执行)
print("→ 关闭数据库连接")
db.close()
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
-
scope="module"确保每个测试模块只运行一次 -
autouse=True让它自动应用,无需在每个测试函数中声明参数 - yield 之前是 setup,之后是 teardown,语义清晰
- 可以安全依赖其他 fixture(如
tmp_path),pytest 自动解析依赖顺序
如果必须用 setup_module(例如兼容老代码)
仅当项目尚未迁移到 fixture 体系、且你明确接受其局限性时才考虑。需同时满足以下条件:
- 函数必须定义在测试文件的最外层,名字严格为
setup_module(注意不是setup_module_或带下划线变体) - 函数必须接收且仅接收一个参数:
module(即当前模块对象) - pytest 配置中禁用
python_files或python_classes的干扰匹配(避免被误判为测试类) - 不要在
conftest.py中定义同名函数,否则会覆盖
示例(不推荐,仅作对照):
# test_example.py
def setup_module(module):
print(f"setup_module called for {module.__name__}")
module.shared_state = {"ready": True}
<p>def test_a():
assert hasattr(test_example, "shared_state")</p><p>def test_b():
assert test_example.shared_state["ready"] is True
</p>
真正难处理的不是怎么写 setup_module,而是它和 fixture、插件、并行执行之间的隐式冲突——这些地方没有报错,只有静默失效。所以只要项目允许,优先用 @pytest.fixture(scope="module"),别省那几行代码。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










