在 Django + DRF 项目中后期引入自动化测试:设置、需求与最佳实践 - 第1部分
Source: Dev.to
许多 Django REST Framework 项目在开始时会快速开发功能,却没有自动化测试套件。起初这看起来很高效,但随着外键增多、序列化器变得嵌套以及系统复杂度提升,手动测试变得脆弱且极其耗时。
本系列的两篇文章将完整演示如何 在已有的 Django REST Framework 项目中引入 pytest,即使你已经深入开发也不例外。
第 1 部分涵盖
- 为什么 pytest 是 Django + DRF 的理想选择
- 安装 pytest 并配置项目级设置
- 创建单独的测试设置文件
- 为 PostgreSQL 设置专用的测试数据库
- 为 API 客户端和测试用户编写 fixtures
- 安全地处理自定义用户模型
- 为可靠运行测试做好项目准备
第 2 部分将展示基于 Blog → Writer → Category → SocialMediaMeta 场景的真实测试案例。
为什么要在后期添加测试?
许多团队会把测试推迟到:
- 模型已基本稳定
- 视图和序列化器开始积累业务逻辑
- 手动测试变得缓慢或容易出错
- 重构风险增大
- Bug 频繁出现
- 新成员加入时的上手成本过高
好消息是:只要正确分离测试配置,pytest 完全可以干净地集成到大型、活跃的 Django 项目中。
安装 pytest 及所需插件
pip install pytest pytest-django pytest-cov Faker
这些工具提供:
pytest– 快速、表达力强的测试框架pytest-django– Django ORM、fixture、数据库初始化等支持pytest-cov– 代码覆盖率统计Faker– 生成随机测试数据
在项目根目录创建 pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = project.settings.test
python_files = tests.py test_*.py *_tests.py
addopts = --reuse-db -x
关键点
- 明确指向 测试设置 文件。
--reuse-db能显著加快测试速度。-x在首次失败后立即停止(可选,但在早期非常实用)。
创建 settings/test.py
from .local import *
DATABASES["default"]["NAME"] = "test_db"
AUTH_PASSWORD_VALIDATORS = []
TEST_USER = {
"id": 999,
"email": "testuser@example.com",
}
(a) 独立的数据库
测试时绝不能触及开发数据库。
(b) 禁用密码校验器
避免因密码复杂度要求导致测试失败。
(c) TEST_USER
用于绕过复杂的注册流程(OTP、邮件验证、自定义用户管理器逻辑)。
PostgreSQL:创建专用的测试数据库
CREATE DATABASE test_db;
GRANT ALL PRIVILEGES ON DATABASE test_db TO your_db_user;
ALTER DATABASE test_db OWNER TO your_db_user;
手动创建数据库可以避免出现令人头疼的:
permission denied to create database
添加 tests/ 目录结构
tests/
│── __init__.py
│── conftest.py
│── test_blog_creation.py
│── test_blog_listing.py
│── test_nested_blog_response.py
│── test_signals_blog_metadata.py
这里的关键文件是 conftest.py。
创建包含关键 Fixtures 的 conftest.py
import pytest
from django.contrib.auth import get_user_model
from blogs.models import Writer, Category
@pytest.fixture
def test_user(db, settings):
User = get_user_model()
data = settings.TEST_USER
return User.objects.create(
id=data["id"],
email=data["email"],
is_active=True,
)
@pytest.fixture
def api_client(test_user):
from rest_framework.test import APIClient
client = APIClient()
client.force_authenticate(test_user)
return client
@pytest.fixture
def writer(db):
return Writer.objects.create(
name="Jane Writer",
email="jane@example.com",
)
@pytest.fixture
def category(db):
return Category.objects.create(
title="Technology",
slug="tech",
)
这些 fixtures 提供:
- 已认证的 API 客户端(无需登录/OTP 步骤)
- 可复用的测试用户
- 稳定的外键依赖
第一次运行测试
pytest -s
如果配置无误,pytest 将创建测试数据库并成功运行所有测试。
第 2 部分预告:真实的 DRF 测试用例
在下一节我们将讨论:
- Blog + Writer + Category + SocialMediaMeta 示例模型
- 嵌套序列化器
- 外键创建测试
- 信号与反向关系
- 错误校验测试
- 嵌套 JSON 结构的测试
- 认证请求的测试