pytest-django没生效的最常见原因是pytest未加载Django配置,需在含manage.py的根目录运行,并配置pytest.ini指定DJANGO_SETTINGS_MODULE和django_find_project=true;测试需声明db fixture以操作真实数据库。

pytest-django没生效,Django设置找不到
最常见的情况是 pytest 启动时压根没加载 Django 配置,报错类似 django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured。根本原因是 pytest 没识别到 Django 项目结构,也没运行 django.setup()。
必须在项目根目录(即含 manage.py 的目录)下运行 pytest,且确保存在 pytest.ini 或 pyproject.toml 配置文件。推荐用 pytest.ini:
[tool:pytest] DJANGO_SETTINGS_MODULE = "myproject.settings" python_files = test_*.py django_find_project = true
django_find_project = true 会让插件自动向上查找 manage.py;如果项目结构特殊(比如 manage.py 不在根目录),就得显式指定 django_settings_module 并手动调用 django.setup() —— 但这种情况极少,优先检查路径和配置位置。
测试数据库不清理,test_user被残留数据干扰
pytest-django 默认使用事务型测试数据库(TransactionTestCase 行为),但不会自动清空每次测试后的数据。如果你在测试里创建了 User.objects.create(username="test_user"),下次同名测试可能因唯一约束失败,或查到“不该存在的”旧数据。
立即学习“Python免费学习笔记(深入)”;
正确做法是依赖 pytest-django 提供的 db fixture:
- 所有需要真实数据库写入的测试函数,必须声明
def test_something(db):——dbfixture 会自动创建新事务并在测试结束回滚 - 避免在测试中直接调用
TestCase.setUpTestData();那是 unittest 风格,pytest 下无效 - 若需跨测试复用数据(极少见),改用
transactional_dbfixture,但要自己负责清理
没加 db 参数的测试函数,默认走内存 SQLite(无持久化),Model.objects.all() 永远为空 —— 这不是 bug,是设计如此。
工厂类(factory_boy)和 pytest-django 配合出错
用 factory_boy 创建模型实例时,常遇到 IntegrityError: NOT NULL constraint failed,尤其对 ForeignKey 字段。这不是 factory 问题,而是 factory 默认不触发 Django 的 model validation,也不自动处理外键关联。
关键点:
- 给 factory 声明
class Meta:中的django_get_or_create = ("username",)可避免重复创建 - 外键字段必须显式提供,或用
SubFactory关联另一个 factory,不能留空 - 在测试函数里用
dbfixture 后,再调用MyModelFactory.create()才真正写入测试 DB;只用.build()不入库
示例:
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
django_get_or_create = ("username",)
<pre class='brush:python;toolbar:false;'>username = "alice"
email = "alice@example.com"def test_user_profile_exists(db): user = UserFactory.create() # 注意是 create(),不是 build() assert user.profile is not None
测试运行慢,每次重载整个 Django 应用
默认情况下,pytest-django 在每个测试文件开始前都重新初始化 Django 配置,导致启动延迟明显,尤其在大型项目中。
提速方法:
- 用
--reuse-db参数:第一次运行建库,后续跳过 migrate,大幅缩短冷启动时间(注意:手动改过 migration 后需加--create-db强制重建) - 把耗时 setup 拆到模块级 fixture,而非每个测试函数都执行:
@pytest.fixture(scope="module") - 禁用不需要的 Django APP:在
pytest.ini加django_debug_mode = false,并确保settings.TESTING = True时关闭日志、缓存等中间件
别为了省事在 conftest.py 里反复调用 django.setup() —— pytest-django 已接管这事,手动干预反而破坏事务隔离。
测试模型本身不难,难的是让环境稳住、数据干净、反馈够快。最容易忽略的是 db fixture 的显式声明和 pytest.ini 的位置 —— 其他问题基本都从这里衍生。


















