pytest-django 更适合日常开发因其支持fixture复用、参数化测试、细粒度范围控制及清晰错误堆栈;调试时可直接运行单个测试函数,但需显式配置django_settings_module等。

pytest-django 为什么比 Django 自带 test runner 更适合日常开发
因为 pytest-django 天然支持 fixture 复用、参数化测试、更细粒度的测试范围控制(比如只跑某个模型的测试),而且错误堆栈更清晰。Django 自带的 manage.py test 在调试单个测试函数时略显笨重,而 pytest 可直接运行 pytest tests/test_models.py::test_user_creation —— 这对快速验证模型逻辑非常关键。
容易踩的坑:pytest 默认不识别 Django 设置,必须显式配置;否则会报 django.core.exceptions.ImproperlyConfigured: Requested setting DATABASES, but settings are not configured。
最简可用的 pytest-django 配置步骤
只需三步,不改项目结构也能跑起来:
- 安装插件:
pip install pytest-django - 在项目根目录(与
manage.py同级)新建pytest.ini,内容为:[tool:pytest] DJANGO_SETTINGS_MODULE = myproject.settings python_files = test_*.py python_classes = Test* python_functions = test_*
- 确保
myproject.settings能被 Python 导入(即该路径在PYTHONPATH中,或已通过sys.path添加);若用src/结构,需在pytest.ini中加addopts = --pythonpath src
测试 Django 模型时必须用的 pytest fixture
db 和 transactional_db 是核心 fixture,它们决定数据库是否真的写入:
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
-
def test_user_save(db):→ 使用事务 + rollback,速度快,适合大多数字段校验、save()行为测试 -
def test_user_post_save_signal(transactional_db):→ 真实提交事务,用于测试信号(如post_save)、外键级联、数据库触发器等场景 - 漏掉
dbfixture 会报DatabaseWrapper is not accessible before django.setup()或静默跳过数据库操作 - 不要手动调用
django.setup()——pytest-django已接管,重复调用会导致AppRegistryNotReady
避免测试污染:如何安全地重用测试数据
模型测试中常需要预置几条记录,但直接在 setUp() 里创建容易引发事务嵌套或 ID 冲突。推荐方式是用 pytest 的 pytest.fixture 声明式构造:
@pytest.fixture
def active_user(db):
return User.objects.create(username="alice", is_active=True)
<p>def test_user_is_active(active_user):
assert active_user.is_active</p>
注意点:
- fixture 名必须和函数参数名一致,否则不会注入
- 若 fixture 依赖
db,它自己也得声明db参数(如上例中db已隐含在函数签名里) - 不要在 fixture 里用
yield做清理 ——pytest-django的dbfixture 本身已保证每个测试用独立事务快照 - 批量插入用
User.objects.bulk_create([...]),别用循环create(),否则测试变慢且可能触发多余信号
真正麻烦的是跨测试共享状态(比如缓存、Celery 任务队列),这些不在 db fixture 管理范围内,得单独 mock 或重置。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










