pytest-django-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesepytest-django Testing Patterns
pytest-django 测试模式
TDD Workflow (RED-GREEN-REFACTOR)
TDD工作流(红-绿-重构)
Always follow this cycle:
- RED: Write a failing test first that describes desired behavior
- GREEN: Write minimal code to make the test pass
- REFACTOR: Clean up code while keeping tests green
- REPEAT: Never write production code without a failing test
Critical rule: If implementing a feature or fixing a bug, write the test BEFORE touching production code.
请始终遵循此循环:
- 红:先编写一个失败的测试,描述期望的行为
- 绿:编写最少的代码让测试通过
- 重构:在保持测试通过的同时清理代码
- 重复:永远不要在没有失败测试的情况下编写生产代码
重要规则:如果要实现功能或修复bug,在修改生产代码之前先编写测试。
Essential pytest-django Patterns
核心pytest-django模式
Database Access
数据库访问
- Use on any test touching the database
@pytest.mark.django_db - Apply to entire module:
pytestmark = pytest.mark.django_db - Transactions roll back automatically after each test
- 在任何涉及数据库的测试上使用装饰器
@pytest.mark.django_db - 应用到整个模块:
pytestmark = pytest.mark.django_db - 每个测试完成后事务会自动回滚
Fixtures for Test Data
测试数据的Fixtures
Use Factory Boy for models, pytest fixtures for setup:
-
Factories: Create model instances with realistic data ()
UserFactory()- Use for unique fields
factory.Sequence() - Use for realistic fake data
factory.Faker() - Use for foreign keys
factory.SubFactory() - Use for M2M relationships
@factory.post_generation
- Use
-
Fixtures: Setup clients, auth state, or shared resources
- fixture: Django test client
client - Create fixture:
auth_clientfor authenticated requestsclient.force_login(user) - Define in for reuse across test files
conftest.py
使用Factory Boy处理模型,pytest fixtures处理前置设置:
-
工厂:创建带有真实数据的模型实例()
UserFactory()- 使用生成唯一字段
factory.Sequence() - 使用生成真实的模拟数据
factory.Faker() - 使用处理外键关联
factory.SubFactory() - 使用处理多对多关系
@factory.post_generation
- 使用
-
Fixtures:设置客户端、认证状态或共享资源
- fixture:Django测试客户端
client - 创建fixture:通过
auth_client实现已认证请求client.force_login(user) - 在中定义,以便在多个测试文件中复用
conftest.py
Test Organization
测试组织
Structure tests to mirror app structure:
tests/
├── apps/
│ └── posts/
│ ├── test_models.py
│ ├── test_views.py
│ └── test_forms.py
├── factories.py
└── conftest.pyGroup related tests in classes:
- Name classes (e.g.,
TestComponentName)TestPostListView - Name test methods descriptively:
test_<action>_<expected_outcome> - Use for testing multiple scenarios
@pytest.mark.parametrize
测试结构与应用结构保持一致:
tests/
├── apps/
│ └── posts/
│ ├── test_models.py
│ ├── test_views.py
│ └── test_forms.py
├── factories.py
└── conftest.py将相关测试分组到类中:
- 类命名为(例如
TestComponentName)TestPostListView - 测试方法命名要具有描述性:
test_<动作>_<预期结果> - 使用测试多种场景
@pytest.mark.parametrize
What to Test
测试内容
Views
视图
- Status codes: Correct HTTP responses (200, 404, 302)
- Authentication: Authenticated vs anonymous behavior
- Authorization: User can only access their own data
- Context data: Correct objects passed to template
- Side effects: Database changes, emails sent, tasks queued
- HTMX: Check header returns partial template
HTTP_HX_REQUEST
- 状态码:正确的HTTP响应(200、404、302)
- 认证:已认证用户与匿名用户的行为差异
- 授权:用户只能访问自己的数据
- 上下文数据:传递给模板的对象正确
- 副作用:数据库变更、邮件发送、任务入队
- HTMX:检查头是否返回部分模板
HTTP_HX_REQUEST
Forms
表单
- Validation: Valid data passes, invalid data fails with correct errors
- Edge cases: Empty fields, max lengths, unique constraints
- Clean methods: Custom validation logic works
- Save behavior: Objects created/updated correctly
- 验证:有效数据通过验证,无效数据返回正确错误信息
- 边界情况:空字段、最大长度、唯一约束
- Clean方法:自定义验证逻辑正常工作
- 保存行为:对象被正确创建/更新
Models
模型
- Methods: , custom methods return expected values
__str__ - Managers/QuerySets: Custom filtering works correctly
- Constraints: Database-level validation enforced
- Signals: Pre/post save hooks execute correctly
- 方法:、自定义方法返回预期值
__str__ - 管理器/查询集:自定义过滤逻辑正常工作
- 约束:数据库级别的验证被正确执行
- 信号:保存前后的钩子函数正确执行
Celery Tasks
Celery任务
- Mock external calls: Patch HTTP requests, email sending, etc.
- Test logic only: Don't test actual async execution
- Idempotency: Running task multiple times is safe
- 模拟外部调用:Patch HTTP请求、邮件发送等操作
- 仅测试逻辑:不要测试实际的异步执行过程
- 幂等性:多次执行任务是安全的
Django-Specific Testing Patterns
Django特定测试模式
Testing HTMX Responses
测试HTMX响应
Check partial template rendered when header present:
HX-Request- Pass to client request
HTTP_HX_REQUEST="true" - Assert contains partial template name
response.templates
当存在头时,检查是否渲染了部分模板:
HX-Request- 向客户端请求传递
HTTP_HX_REQUEST="true" - 断言包含部分模板名称
response.templates
Testing Permissions
测试权限
Create authenticated vs anonymous client fixtures:
- Test redirect/403 for unauthorized access
- Test success for authorized access
创建已认证和匿名客户端fixture:
- 测试未授权访问时的重定向/403状态
- 测试授权访问时的成功响应
Testing QuerySets
测试查询集
Verify efficient queries:
- Create test data with factories
- Execute query
- Assert correct objects returned/excluded
- Verify related objects loaded with /
select_related()prefetch_related()
验证查询的效率:
- 使用工厂创建测试数据
- 执行查询
- 断言返回/排除的对象正确
- 验证通过/
select_related()加载关联对象prefetch_related()
Testing Forms with Model Instances
测试带模型实例的表单
Pass instance to form for updates:
form = MyForm(data=new_data, instance=existing_obj)- Verify updates, doesn't create
form.save()
传递实例给表单以进行更新:
form = MyForm(data=new_data, instance=existing_obj)- 验证执行更新而非创建
form.save()
Common Patterns
通用模式
Parametrize multiple scenarios:
Use for testing various inputs
@pytest.mark.parametrize("input,expected", [...])Mock external services:
Use to avoid actual HTTP calls, emails, file operations
mocker.patch()Check database changes:
- Assert after creation
Model.objects.filter(...).exists() - Assert for deletions
Model.objects.count() == expected - Use to verify updates
refresh_from_db()
Test error handling:
- Invalid form data produces correct errors
- Failed operations return error responses
- User sees appropriate error messages
参数化多种场景:
使用测试各种输入
@pytest.mark.parametrize("input,expected", [...])模拟外部服务:
使用避免实际的HTTP调用、邮件发送、文件操作
mocker.patch()检查数据库变更:
- 创建操作后断言
Model.objects.filter(...).exists() - 删除操作后断言
Model.objects.count() == expected - 使用验证更新
refresh_from_db()
测试错误处理:
- 无效表单数据返回正确错误信息
- 失败操作返回错误响应
- 用户看到合适的错误提示
Running Tests
运行测试
bash
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 reportbash
uv run pytest # 运行所有测试
uv run pytest -x # 遇到第一个失败即停止
uv run pytest --lf # 运行最后失败的测试
uv run pytest -x --lf # 仅运行最后失败的测试,遇到第一个失败即停止
uv run pytest -k "test_name" # 运行匹配指定模式的测试
uv run pytest tests/apps/posts/ # 运行指定目录下的测试
uv run pytest --cov=apps # 生成覆盖率报告Common Pitfalls
常见陷阱
- Forgetting : Results in "Database access not allowed" errors
@pytest.mark.django_db - Not using factories: Creating instances manually is verbose and brittle
- Testing implementation: Test behavior and outcomes, not internal implementation details
- Skipping TDD: Writing tests after code means tests follow implementation, missing edge cases
- Over-mocking: Mock external dependencies, not your own code
- Testing framework code: Don't test Django's ORM, form validation, etc. Test YOUR logic
- 忘记使用:会导致“不允许数据库访问”错误
@pytest.mark.django_db - 不使用工厂:手动创建实例繁琐且脆弱
- 测试实现细节:测试行为和结果,而非内部实现细节
- 跳过TDD:在编写代码后再写测试会导致测试跟随实现,遗漏边界情况
- 过度模拟:只模拟外部依赖,不要模拟自己的代码
- 测试框架代码:不要测试Django的ORM、表单验证等,只测试你自己的逻辑
Setup Requirements
配置要求
In :
pyproject.tomltoml
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "config.settings.test"
python_files = ["test_*.py"]
addopts = ["--reuse-db", "-ra"]In :
Define shared fixtures (auth_client, common factories, etc.)
conftest.py在中:
pyproject.tomltoml
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "config.settings.test"
python_files = ["test_*.py"]
addopts = ["--reuse-db", "-ra"]在中:
定义共享fixture(auth_client、通用工厂等)
conftest.pyIntegration with Other Skills
与其他技能的集成
- systematic-debugging: When fixing bugs, write failing test first to reproduce
- django-models: Test custom managers, QuerySets, and model methods
- django-forms: Test form validation, clean methods, and save behavior
- celery-patterns: Test task logic with mocked external dependencies
- systematic-debugging:修复bug时,先编写失败测试以复现问题
- django-models:测试自定义管理器、查询集和模型方法
- django-forms:测试表单验证、clean方法和保存行为
- celery-patterns:通过模拟外部依赖测试任务逻辑