如何创建pytest Fixture实现测试模块级数据库清理?FastAPI+Pony ORM
解决FastAPI+Pony ORM项目中pytest测试的数据库清理问题
核心问题分析
你之前用scope="module"的fixture没生效,大概率是这几个原因:
- 未正确关闭数据库会话,导致清空操作被锁或未生效
- 误用
droptables(cleardata=True)(该方法是删除表结构,而非仅清空数据,后续测试可能因表不存在报错) - 未设置
autouse=True,fixture未自动应用到所有测试模块
解决方案:自动清理的pytest全局Fixture
在test/conftest.py文件中编写全局fixture(pytest会自动加载该文件,无需在测试中手动导入),确保每个测试模块执行前后数据库都是空的。
方案1:仅清空数据(推荐,速度更快)
适合表结构固定的场景,只清空表内数据,保留表结构:
import pytest from app.db import db # 替换为你项目中Database对象的实际导入路径 @pytest.fixture(scope="module", autouse=True) def clean_database_per_module(): # 测试模块执行前:清空所有表数据 with db.session: db.session.rollback() # 回滚未提交的会话 db.session.close() # 关闭现有会话避免锁表 db.truncate_all_tables() # Pony ORM提供的批量清空数据方法 yield # 执行当前测试模块的所有用例 # 测试模块执行后:再次清空数据,确保下一个模块环境干净 db.truncate_all_tables()
方案2:重建表结构
适合测试中会修改表结构的场景,删表后重新创建:
import pytest from app.db import db @pytest.fixture(scope="module", autouse=True) def reset_database_per_module(): # 测试前:删除所有表并重建 db.drop_all_tables(with_all_data=True) db.generate_mapping(create_tables=True) yield # 测试后:删除所有表 db.drop_all_tables(with_all_data=True)
关键配置说明
scope="module":表示fixture在每个测试模块(.py文件)执行前后各运行一次autouse=True:自动应用到所有测试模块,无需在测试用例中显式调用- 会话处理:必须先回滚+关闭会话,避免数据库锁导致清空操作失败
测试运行
直接在项目根目录执行命令即可批量运行所有测试:
pytest test/
额外注意事项
- 必须使用测试专用数据库:绝对不能在生产/开发数据库上运行测试清理逻辑
- 若需每个测试函数都清空数据库:将
scope="module"改为scope="function" - 测试用例中的数据库操作:执行完后记得提交或回滚,避免会话残留数据
内容的提问来源于stack exchange,提问作者Adolfo Banchio
相关产品推荐
相关产品推荐

