使用 pytest-django、测试驱动开发(TDD)方法论、factory_boy、Mock 模拟、覆盖率统计以及 Django REST Framework API 测试的 Django 测试策略。
View on GitHubxu-xiang/everything-claude-code-zh
everything-claude-code
February 5, 2026
Select agents to install to:
npx add-skill https://github.com/xu-xiang/everything-claude-code-zh/blob/main/skills/django-tdd/SKILL.md -a claude-code --skill django-tddInstallation paths:
.claude/skills/django-tdd/# Django TDD 测试指南
使用 pytest、factory_boy 和 Django REST Framework 对 Django 应用进行测试驱动开发(TDD)。
## 何时激活
- 编写新的 Django 应用程序时
- 实现 Django REST Framework API 时
- 测试 Django 模型(Models)、视图(Views)和序列化器(Serializers)时
- 为 Django 项目搭建测试基础设施时
## Django 的 TDD 工作流
### 红-绿-重构循环(Red-Green-Refactor Cycle)
```python
# 步骤 1:红色(RED) - 编写失败的测试
def test_user_creation():
user = User.objects.create_user(email='test@example.com', password='testpass123')
assert user.email == 'test@example.com'
assert user.check_password('testpass123')
assert not user.is_staff
# 步骤 2:绿色(GREEN) - 编写代码使测试通过
# 创建 User 模型或工厂(Factory)
# 步骤 3:重构(REFACTOR) - 在保持测试通过的前提下优化代码
```
## 环境搭建
### pytest 配置
```ini
# pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = config.settings.test
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts =
--reuse-db
--nomigrations
--cov=apps
--cov-report=html
--cov-report=term-missing
--strict-markers
markers =
slow: 标记为耗时较长的测试
integration: 标记为集成测试
```
### 测试设置(Settings)
```python
# config/settings/test.py
from .base import *
DEBUG = True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
# 禁用迁移以提升速度
class DisableMigrations:
def __contains__(self, item):
return True
def __getitem__(self, item):
return None
MIGRATION_MODULES = DisableMigrations()
# 使用更快的密码哈希算法
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]
# 邮件后端配置
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# Celery 始终同步执行
CELERY_TASK_ALWAYS_EAGER = True
CELERY_TASK_EAGER_PROPAGATES = True
```
### conftest.py
```python
# tests/conftest.py
import pytest
from django.utils import timezone
from django.contrib.auth import get_user_model
User = get_user_model()
@pytest.fixture(autouse=True)
def timezone_settings(settings):
"""确保时区一致。"""
settings.TIME_ZONE = 'UTC'
@pytest.fixture
def user(db):