- Django 测试的教程:https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial06/
- Django 测试的文档:https://docs.djangoproject.com/zh-hans/3.1/topics/testing/
在后端开发中,自己写测试样例还是非常重要的,不然每次修改程序以后手动测试,工作量又大,还很难测完整。
Django runserver 时测试 API
DRF 教程提到,在 runserver
时手动测试看效果时可以使用 httpie
或者其他工具。但是 POST
数据似乎有点麻烦。博主更常使用 Python 的 requests 库。
1 | pip install requests |
1 | from requests import get, post, put, delete |
语法和 django.test.client.Client
几乎一模一样。
Django test 邮件服务
Django test 还会替换掉默认的 SMTP 服务器,改为一个虚拟的、不会真正发送邮件的服务器。
文档:https://docs.djangoproject.com/zh-hans/3.1/topics/testing/tools/#email-services
官方也给了一个读取发件箱的方法,这样每次测试的时候就不用人工查询邮件,而是直接在测试代码里读取邮件信息,再配合正则表达式就可以提取出需要的信息了。下面是一个示例:
1 | from django.core import mail |
上面这个函数自动抓取发送邮件中的 token=XXXXX
字段中的 XXXXX
,保存到 token
变量然后返回。
Django test “修改当前时间”
博主在写签到的 TestCase 的时候,想要修改 now()
时间来进行测试。Google 了一下找到了 mock 的几种写法,这里演示一种(源代码):
1 | from unittest import mock |
Django test 和 Integration Error?
博主在写登录的 TestCase 时出现了很奇怪的现象:正常运行时 API 貌似没有问题,在一个 Test 函数中调用一次 login
函数也没有问题,但如果调用两次 login
函数,Python
解释器会不报错而停止,错误码为 -1073741819 (0xC0000005)
。login()
函数如下:
1 | def login(request): |
test 函数如下:
1 | class LogInTest(TestCase): |
我参考了 Django 文档的 事务 部分,按照官方推荐的方法编写这段代码,但是出了问题。
个人猜测可能是 TestCase 中涉及的数据库回滚和 IntegrityError
触发回滚的冲突?
最终我只能按照 if
的方法替代掉 try-catch
的方法。尽量不要触发 IntegrityError
吧。
Django test 时,POST 和 PATCH 记得添加 content_type=’application/json’
笔者已经两次被这个坑了。第一次是在测试 PATCH 时,使用 django.test.client.Client.patch(path, data)
,返回的 HTTP 状态码为 415 Unsupported media type "application/octet-stream" in request.'
:
添加参数 Client.patch(path, data, content_type='application/json')
就好了。
Getting 415 code with django.test.Client’s patch method
后来,在 POST 的时候莫名其妙发现我写的下面这段 JSON,手动 POST 时能正常工作,但使用 Client.post(path, data)
时,嵌套的 {"id":1}
部分不能被正确识别到。
1 | { |
DEBUG 的时候注意到,response 中包含的 wsgi_request
里面,{"id":1}
就没有被正确提交。猜测可能是 Django Client 没有以 JSON 的形式解析这段代码,于是加上 content_type='application/json'
,就返回 201 Created
了。