在Django下测试与调试REST API的方法详解
作者:Mr-Bruce 发布时间:2023-05-19 16:09:32
对于大多数研发人员来说,都期望能找到一个良好的测试/调试方法,来提高工作效率和快速解决问题。所谓调试,偏重于对某个bug的查找、定位、修复;所谓测试,是检验某个功能是否达到预期效果。测试发现问题后进行调试,从而解决问题。
对于后台研发来说,往往没有客户端研发(Windows/Android等等)那样简单有效的DEBUG方法,比如Step by Step。虽然目前有很多IDE可以实现本地调试,但是因为后台研发的环境复杂,你很难在一台机器上模拟所有的环境,比如线上的数据库只能在内网访问等等,所以很多时候需要在服务器(DEV/STG/PROD)上进行调试和测试工作。本文尝试介绍一些Django Web服务下调试/测试REST API的方法,因为是方法,那自然仁者见仁智者见智,所以也许你觉得会有用,也许会觉得毫无道理。
首先要说的是,在服务器环境,针对Django Web服务,print log是最简单有效的方法。python的语言特性决定了你可以随时添加log,重新run一下就可以看到结果。本文接下来要说的,并不是什么超脱于pring log的超级技巧,而是如何编写代码、利用工具进行有效的调试/测试工作,并尽量做到减少重复性工作。
对于任何一个REST API来说,需要进行测试的内容包括两部分:请求中的各个功能模块是否正常、整个请求是否正常。对于研发人员来说,写完代码后当然要进行一番测试来确认代码是否正常工作、是否符合需求。这时,有人选择先测试一下整个请求是否正常,如果正常就万事大吉,交付给测试同事测试了,如果不正常则进一步查看是哪个功能模块出现问题;有人选择先逐一测试各个功能模块是否正常,在确保各功能模块正常后,再进一步测试整个请求是否正常,然后交付测试。这两种行事风格并没有特别的利弊之说,最好是在不同的情形下选择使用,比如对于简单的功能API,可以使用第一种,而对于复杂的功能API,选择第二种。不管行事风格如何,都会涉及都前面所述的两部分测试内容,即分与合的两部分测试。Django下,常见的有这么两种方法,或者说目前在我们项目组使用最广泛的两种方法:
1. 对于功能模块,使用python manage.py shell来进行调试与测试。该命令帮助我们启动一个python 的shell环境,并自动加载了Django的上下文信息,我们可以在里面import任何函数和类,构建参数,调试/测试其相关的功能。如果需要定位问题,一种方法是在源文件中加入更多的log,一种方法是将该功能模块逐行敲一遍,看看在哪边出现了问题。
2. 对于整个请求,使用工具curl(linux下)或者Advanced REST Client(Windows下,Chome的一个插件)来构建一个Request,发送给后台服务。笔者使用更多的是第二个,其可以构建各个Method的Request,并且可以保存相应的请求,还可以分享你保存的列表给别人使用。发送请求后,通过后台log来查看请求是否正常及相关的异常错误问题,你可以使用tail -f /var/log/test.log来查看动态log信息。
在合适的位置增加规范化的log对于后台服务来说,是一件非常重要的事情,能帮助我们在线上环境及时发现问题,log的书写应该包括相应的Tag,ErrorCode等等信息,方便查找。
上述两个方法,可以很好的对Django下的Web服务进行调试/测试,但是却有着一些缺憾。对应第一种方法,通过python manage.py shell进行功能测试,意味着每次都需要启动一个shell,每次都需要将相应的代码敲一遍,存在着重复性的工作,其实这种方法更适用于应对特殊的CASE,而不是针对Common的功能进行调试/测试。对于第二种方法,首先,当你想增加一些log时,你需要重启一下服务才能生效,而这种情况在生产环境就比较棘手;其次,通过这种方法进行测试,你没有办法在程序中处理一些Response的结果。
Python和Django自带了一些测试框架和工具,而充分利用这些,正好可以解决上述两种方法的缺憾。常用的一些测试框架和工具有:
1)单元测试框架TestCase;
2)Django的Test Client,类似curl的工具,是一个类似内置浏览器的工具,可以发起一个请求,并拿到对应的response内容;
3)RequestFactory,允许构建一个request参数,实现象调用函数一样调用一个view的请求函数,可以绕过middleware。
结合前面两种方法的缺憾和上述的测试框架/工具,下面介绍两种笔者常用的两种调试/测试方法:
1. 对于功能模块,采用单元测试的方法。单元测试常见于TDD的研发流程中,一方面可以验证所写的程序模块运行后的行为是否符合设计的测试用例,另一方面可以在修改代码后,快速验证是否改出了问题,是否与原有行为保持一致。采用单元测试的方法,既可以实现功能模块的调试/测试功能,也能有效的避免重复性工作,有效的弥补了前面所述的第一种方法的缺点。
python本身自带了一套unittest框架,而diango对于它又做了一层封装,可以根据喜好选择使用,笔者通常还是习惯使用python自带的单元测试框架。一个简单的单元测试代码如下:
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# check that s.split fails when the separator is not a string
with self.assertRaises(TypeError):
s.split(2)
if __name__ == '__main__':
unittest.main()
2. 对于整个请求,采用RequestFactory来实现类函数式调用的方法,从而可以实现调用view的请求函数。采用这个方法,可以有效避免前面第二种方法中需要重启服务的缺陷,当你修改了代码后,只要重新reload一下模块,即可实现新的调用;同时,你也可以在代码中拿到对应的response内容,做必要的校验处理。
然而,对于我们使用rest framework 框架来做REST API开发来说,Django原生的RequestFactory还是有一点缺陷,就是不能做authenticate。因为rest framework中的authenticate是做在request前面的,而不是在middleware中,所以采用原生的RequestFactory无法绕过authenticate。不过,rest framework又重新封装了一个APIRequestFactory类,提供了相关的模拟鉴权功能,常见的用法如下:
from rest_framework.test import APIRequestFactory
from rest_framework.test import force_authenticate
# Using the standard RequestFactory API to create a form POST request
factory = APIRequestFactory()
request = factory.post('/notes/', {'title': 'new idea'}, format='json')
# force authenticate
user = User.objects.get(username='olivia')
force_authenticate(request, user=user)
# call the view request
view = AccountDetail.as_view()
response = view(request)
上面所述的方法,只是笔者目前常用的四种方法,在实际工作中根据需要进行选择使用。当然,我相信还有更多更好的其他方法。
这篇在Django下测试与调试REST API的方法详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
来源:https://blog.csdn.net/zwgdft/article/details/52981310
猜你喜欢
- 这篇文章主要介绍了基于python操作ES实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可
- 为某国税局开发一综合 * ,需要建立一个庞大的国税系统通讯录数据库,从各省、市到每名具体工作人员,项目较多,该如何设计各表呢?数据库的表设计
- 1 类继承Python 是面向对象的编程语言,因此支持面向对象的三大特性之一:继承。继承是代码重用的一种途径,Python 中的继承就像现实
- 相信有很多人有用程序向Excel导数据的需求, 且做过. 一般导出一些文本数据是很方便的, 可选方法很多, 比如拼接文本字符串存.cvs格式
- PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、Proje
- 1. 横排往下会影响阅读速度。如12345678的单排单列数字,肯定是竖排阅读快。但多行多列的整块信息,横排并不见得就比竖排慢,比如所有简体
- 选择最实用来谈一下首先,你要慎重选择你就业的城市。这点是目前多数人都忽略的重要因素。无论你的设计思路和发展方向都要依托你所在城市来作为载体。
- 这个效果前些日子有人在论坛问起,今天有空研究了下。我打了原创标记,因为我在写这个方法时的确没有参考过别人的代码。我的方法其实就是层遮罩加AL
- 1. Jupyter 默认目录调整首先要找到jupyter生成的配置文件 jupyter_notebook_config.py 。如果没有,
- 有些时间没更新blog了,这两天为了更新<code collection>,于是重写了语法高亮的模块,这次是一个引擎,你可以根据
- js关于 byval 与 byref 二者区别: byval 传递数值,实参和形参分处不同的内存单元,互不干扰! byref 传递地址,实参
- 超文本传输协议http构成了万维网的基础,它利用URI(统一资源标识符)来识别Internet上的数据,而指定文档地址的URI被称为URL(
- 一个有点绕的例子,用PyScripter调试器步进跟踪可以看清楚对 象结构的具体细节。对原作改变了一下,在未定义子对象属性时__getite
- 快速测试创建项目与appdjango-admin startproject mysitedjango-admin startapp app1
- asp之字符串函数示例用字符串函数对字符串进行截头去尾、大小写替换等操作。函数语 * 能LenLen(string|varname)返回字符串
- 本文实例讲述了Python实现的多线程http压力测试代码。分享给大家供大家参考,具体如下:# Python version 3.3__au
- 如下所示:# coding=utf-8import signalimport timedef set_timeout(num, callba
- 用python的matplotlib画图时,往往需要加图例说明。如果不设置任何参数,默认是加到图像的内侧的最佳位置。import matpl
- 昨天去面试,百度题果然不一样,笔试我就蒙了,现在能记住两道题,笔试:1、title和alt 区别2、三列布局 左边裂固定宽度左对齐,右边列固
- islower()方法判断检查字符串的所有的字符(字母)是否为小写。语法以下是islower()方法的语法:str.islowe