Test Writer 是一个面向 Django/DRF 项目的测试编写技能,目标是让测试读起来像验收标准,并且在重构后依然有效。它主张通过公开接缝(API 端点、服务函数)测试行为,而不是针对私有辅助函数。
用途
为项目中的新增或既有 Django/DRF 代码编写 pytest-django 测试,覆盖 API 测试、权限与作用域测试、服务测试、查询次数等。
使用方式
第一步是先匹配项目现状:读取 pytest.ini、pyproject.toml 或 setup.cfg,了解 pytest 设置、标记与 DJANGO_SETTINGS_MODULE;阅读从根目录到应用层的每个 conftest.py,复用其中的夹具(如 api_client、user、org、已认证客户端),而不是新建;查看工厂(factories.py、factory_boy)或 fixtures/baker,按既有文件风格为新模型补充工厂;并参考同一应用中一个现有测试文件的命名、类式或函数式风格以及认证设置方式。如果项目使用 Django TestCase 而非 pytest,则沿用该方式。
第二步是在动笔前列出要测的用例:每条验收标准的正常路径;权限,包括匿名访问(401)、角色不符(403),以及跨租户场景——来自其他组织或账号的用户访问他人组织对象时得到 404(或项目约定的 403);校验,包括每个必填字段缺失、每个有规则约束的非法值;状态规则,例如不能作废已作废的发票、锁定后不能编辑;副作用,例如邮件、入队任务、Webhook、审计记录;列表端点的查询次数。对于 Django/DRF 自身的行为(如 CharField(max_length=10) 拒绝 11 个字符),除非属于验收标准,否则跳过。
第三步是编写测试。技能给出了示例代码结构:使用 pytestmark = pytest.mark.django_db,按行为命名测试(如 test_member_cannot_void),用 reverse 构造 URL,通过夹具创建对象并断言响应状态与数据库状态,用 parametrize 覆盖多种状态,用 django_assert_max_num_queries 限制列表端点查询数。可用的 pytest-django 能力包括 settings 夹具覆盖配置、mailoutbox、django_assert_num_queries 与 django_assert_max_num_queries、django_capture_on_commit_callbacks(在测试中执行 on_commit 钩子)。时间控制沿用项目已有方案(freezegun、time-machine),不擅自新增。Mock 只用于边界:出站 HTTP、支付服务商、.delay();不要 mock ORM 或被测代码。
第四步是运行与检查:先跑新文件,再跑该应用的测试,条件允许时跑全量套件;确认每个新测试在对应行为被破坏时会失败,可临时改坏代码抽查一两个。
规则与限制
不得用与代码相同的方式重算期望值来做断言,应使用字面期望值;不得使用 sleep、不得依赖测试顺序、不得访问真实网络;不得为了让新代码通过而放宽既有测试,既有测试失败时应报告并询问。