mcpField
P
pytest-django-patterns

pytest-django-patterns

github.com/waldencui测试与质量17855 次安装32 周前更新
代码仓库

关于 pytest-django-patterns

面向 Django 项目的 pytest-django 测试模式指南,供开发者编写和组织测试。它强调先测试后实现,并提供数据库、视图、表单、模型及任务的测试方法。

主要功能

  1. 01RED-GREEN-REFACTOR 测试流程
  2. 02数据库标记与测试数据工厂
  3. 03按应用组织测试文件
  4. 04视图、表单和模型测试
  5. 05模拟外部服务与任务

适用场景

  1. 01为新功能采用测试驱动开发
  2. 02验证 HTMX 视图和权限行为
  3. 03检查表单验证与数据库变更

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/waldencui/claude-code-django --skill pytest-django-patterns

安装后在 Claude Code 中输入/pytest-django-patterns确认已加载。

详细介绍

pytest-django 测试模式

TDD 工作流(RED-GREEN-REFACTOR)

始终遵循此循环:

  1. RED:先编写一个描述预期行为的失败测试
  2. GREEN:编写最少量的代码,让测试通过
  3. REFACTOR:在保持测试通过的同时清理代码
  4. REPEAT:没有失败测试时,绝不编写生产代码

关键规则:实现功能或修复 Bug 时,先编写测试,再修改生产代码。

pytest-django 基本模式

数据库访问
  • 对任何访问数据库的测试使用 @pytest.mark.django_db
  • 应用于整个模块:pytestmark = pytest.mark.django_db
  • 每个测试结束后,事务都会自动回滚
测试数据的 Fixtures

模型使用 Factory Boy,设置使用 pytest fixtures:

  • Factories:使用真实的数据创建模型实例(UserFactory())

    • 使用 factory.Sequence() 为字段生成唯一值
    • 使用 factory.Faker() 生成逼真的伪数据
    • 使用 factory.SubFactory() 为外键赋值
    • 使用 @factory.post_generation 处理 M2M 关系
  • Fixtures:用于设置客户端、身份验证状态或共享资源

    • client fixture:Django 测试客户端
    • 创建 auth_client fixture:使用 client.force_login(user) 发送经过身份验证的请求
    • 在 conftest.py 中定义,以便在多个测试文件中复用
测试组织

让测试结构与应用结构保持一致:

tests/
├── apps/
│   └── posts/
│       ├── test_models.py
│       ├── test_views.py
│       └── test_forms.py
├── factories.py
└── conftest.py

将相关测试分组到类中:

  • 将类命名为 TestComponentName(例如 TestPostListView)
  • 使用描述性名称命名测试方法:test_<action>_<expected_outcome>
  • 使用 @pytest.mark.parametrize 测试多个场景

测试内容

视图
  • 状态码:正确的 HTTP 响应(200、404、302)
  • 身份验证:已验证身份与匿名用户的行为
  • 授权:用户只能访问自己的数据
  • 上下文数据:传递给模板的对象正确
  • 副作用:数据库变更、邮件发送、任务入队
  • HTMX:检查 HTTP_HX_REQUEST 请求头是否返回部分模板
表单
  • 验证:有效数据通过验证,无效数据产生正确的错误
  • 边界情况:空字段、最大长度、唯一约束
  • Clean 方法:自定义验证逻辑正常运行
  • 保存行为:对象正确创建或更新
模型
  • 方法:__str__ 和自定义方法返回预期值
  • 管理器/QuerySet:自定义筛选正常工作
  • 约束:数据库级验证得到强制执行
  • 信号:保存前后钩子正确执行
Celery 任务
  • 模拟外部调用:模拟 HTTP 请求、邮件发送等
  • 只测试逻辑:不要测试实际的异步执行
  • 幂等性:多次运行任务是安全的

Django 专用测试模式

测试 HTMX 响应

检查存在 HX-Request 请求头时是否渲染了部分模板:

  • 向客户端请求传入 HTTP_HX_REQUEST="true"
  • 断言 response.templates 包含部分模板名称
测试权限

创建已验证身份和匿名用户的客户端 fixtures:

  • 测试未授权访问时的重定向或 403 响应
  • 测试已授权访问时的成功响应
测试 QuerySet

验证查询是否高效:

  • 使用 factories 创建测试数据
  • 执行查询
  • 断言返回或排除的对象正确
  • 验证是否使用 select_related()/prefetch_related() 加载了关联对象
使用模型实例测试表单

更新时向表单传入实例:

  • form = MyForm(data=new_data, instance=existing_obj)
  • 验证 form.save() 会更新对象,而非创建对象

常见模式

参数化多个场景: 使用 @pytest.mark.parametrize("input,expected", [...]) 测试多种输入

模拟外部服务: 使用 mocker.patch() 避免实际发起 HTTP 调用、发送邮件或执行文件操作

检查数据库变更:

  • 创建后断言 Model.objects.filter(...).exists()
  • 删除后断言 Model.objects.count() == expected
  • 使用 refresh_from_db() 验证更新

测试错误处理:

  • 无效的表单数据会产生正确的错误
  • 操作失败会返回错误响应
  • 用户会看到相应的错误消息

运行测试

uv run pytest                    # All tests
uv run pytest -x                 # Stop on first failure
uv run pytest --lf               # Run last failed
uv run pytest -x --lf            # Stop first, last failed only
uv run pytest -k "test_name"     # Run tests matching pattern
uv run pytest tests/apps/posts/  # Specific directory
uv run pytest --cov=apps         # With coverage report

常见陷阱

  • 忘记添加 @pytest.mark.django_db:会导致出现“Database access not allowed”错误
  • 不使用工厂:手动创建实例冗长且脆弱
  • 测试实现细节:测试行为和结果,而非内部实现细节
  • 跳过 TDD:在编写代码后再写测试,会让测试跟随实现,遗漏边界情况
  • 过度模拟:模拟外部依赖,而非你自己的代码
  • 测试框架代码:不要测试 Django 的 ORM、表单验证等;要测试你自己的逻辑

设置要求

在 pyproject.toml 中:

[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "config.settings.test"
python_files = ["test_*.py"]
addopts = ["--reuse-db", "-ra"]

在 conftest.py 中: 定义共享的 fixtures(auth_client、常用工厂等)

与其他技能集成

  • systematic-debugging:修复错误时,先编写失败的测试来复现问题
  • django-models:测试自定义管理器、QuerySet 和模型方法
  • django-forms:测试表单验证、clean 方法和保存行为
  • celery-patterns:使用模拟的外部依赖测试任务逻辑

评论

支持 Markdown