霍格沃兹测试开发学社

《Python测试开发进阶训练营》(随到随学!)
2023年第2期《Python全栈开发与自动化测试班》(开班在即)
报名联系weixin/qq:2314507862

数据包还可以可视化?你只需要这一招

上一篇文章,讲述了charles的使用,很多人依旧迷惑,难道我要用charles手动抓包,手动分析吗?这样效率好低啊!

既然charles称为代理工具,我们自然要利用它的这个特性,比如今天的主角Requests。

我们可以让Requests走代理,用charles抓取Requests发出的数据包,从而达到数据包的可视化,这样的组合是不是让你大开眼界?其实还有更多精彩操作。

1 引言

Requests是一个优雅而简单的python

HTTPS。其实python内置了用于访问网络的资源模块,比如urllib。但是它不如requests简单,优雅,而且缺少许多实用功能。

Requests的使用方法,官方介绍的非常简单明了。这篇文章不会讲解所有命令,而是利用demo教会你怎么配合charles使用。在正式开始之前,你需要知道以下内容:

首先需要利用pip命令安装requests。

$ pip install requests

本篇文章的第一个任务是让Requests与charles结合,完成对testerhome的测试。下面的url是testhome提供的接口,后面的文章将利用这个接口进行测试:

testhome接口:https://testerhome.com/api/v3/topics.json?limit=2

访问这个接口,你会看到一些文本:

本项目github地址:https://github.com/seveniruby/ApiTesting_9Requests

官方文档:https://2.python-requests.org/en/master/

2 使用get方法

get方法是基本的请求方法,下面简短的代码向您展示了如何用get访问testerhome接口:

class TestRequests(object):  
    def test_get(self):  
        r=requests.get("https://testerhome.com/api/v3/topics.json?limit=2")

运行代码,你可以看到返回的结果,这是json格式的数据:

get的方法非常简单,只需要几行简短的代码。但实际使用的过程中,会有一些额外情况。比如有url中带参数怎么办(豆瓣),如果你想往url中传入参数,就需要加入一个dick

r = requests.get('https://www.douban.com/search', params={'q': 'hello', 'cat': '1001'})  
r.url   
---  
# 可以看到,我们的请求url中有了参数  
'https://www.douban.com/search?q=hello&cat=1001'

当然,你也可以向get方法中加入header,依旧需要加入dick

r = requests.get('https://www.douban.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})  
r.text  
---  
  
'<!DOCTYPE html>\n<html>\n<head>\n<meta charset="UTF-8">\n <title>豆瓣(手机版)</title>...'

以上是get方法的几个小demo。有人问,怎么没有charles的身影,不是说要讲charles和Requests的结合吗?别急,后面的post会告诉您答案。

其实post方法和get方法本质上都调用了response方法。response的第一个参数决定使用post还是使用get,这是Requests的内部实现。如果你想知道更多源码内容,请关注霍格沃兹测试学院视频,思寒在课上带你解析Requests部分源码。

3 使用post方法

在打出Requests和charles的组合拳之前,简单介绍下post方法的具体实现。从下面的源码就可以看出,你需要加入一些参数,比如我们要加入代理服务器地址。

下面利用post方法加入一些参数,需要注意的是proxies指定了代理地址:127.0.0.1:7778,这个地址是charles的监听地址。

def test_post(self):  
    r = requests.post(  
        self.url,  
        data={"a":"1","b":"string corntent"},  
        proxies={"https":"http://127.0.0.1:7778",  
                 "http":"http://127.0.0.1:7778"},  
        verify=False)  

我们打开charles,然后运行上面的代码,你会在charles上发现抓取的数据包:

数据包表明,我们发送的是post请求,发送的数据是一个字典,这与Requests中定义的data一模一样:

{"a":1,"b":"string corntent"}

读到这里,你是否比较困惑:“get方法和post方法非常相似,使用方法也几乎一样,他们到底有什么区别?什么时候用get方法,什么时候用post方法呢”

4 post和get的区别

post方法和get方法很像,但他们确实有区别,在wireshark这篇文章中我们讲过。

在神秘而美丽的万维网中,TCP就像是运输汽车,我们用TCP来运输数据,它勤劳而可靠,从不会丢货。

如果路上全是一模一样的运输汽车,那这个公路会一团混乱,因为非常紧急的汽车(警车)可能被前面的汽车拦堵在路上,因为它们都是TCP。

为了避免这种情况发生,警察叔叔制定了交通规则:HTTP。HTTP给汽车分门别类,有GET, POST, PUT, DELETE等等。

HTTP规定,GET请求的汽车,要贴上GET的标签,而且要求把传送的数据放在车顶上(url中)。

如果是POST请求,要贴上POST的标签,并把货物放在车厢里(请求体body)。

当然,你也可以在GET的时候往车厢内(body)偷偷藏点货物;也可以在POST的时候在车顶上(url中)放一些数据。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。

基于上面这条准则,Request的get方法是可以在url中加入请求参数的:

r = requests.get('https://www.douban.com/search', params={'q': 'hello', 'cat': '1001'})  
r.url   
---  
# 可以看到,我们的请求url中有了参数  
'https://www.douban.com/search?q=hello&cat=1001'

但post方法只能在请求体中加入参数:

r = requests.post('https://accounts.douban.com/login', data={'form_email': '1111', 'form_password': '1111'})  
  
# 在请求体中加入参数

5 任务

讲完长篇大论,现在做一个实战:对雪球的json接口测试。

请你用request编写一个test_xueqiu_quote测试用例,发送如下请求,并打印格式化pretty print的结果。下面是对应的curl命令:

curl -k -H 'Cookie: xq_a_token=5806a70c6bc5d5fb2b00978aeb1895532fffe502;u=3446260779' -H 'User-Agent: Xueqiu Android 11.19' -H 'Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4' -H 'Host: stock.xueqiu.com' --compressed 'https://101.201.175.228/v5/stock/portfolio/stock/list.json?_t=1UNKNOWNc60715cb4a61425b311034a49f4aa024.3446260779.1563002521424.1563005246620&_s=8c6b2d&category=1&pid=-1&size=10000&x=1.3&page=1'

输入curl命令,你会得到下面的返回结果 :

{"data":{"pid":-1,"category":1,"stocks":[{"symbol":"FB","name":"Facebook","type":0,"remark":"","exchange":"NASDAQ","created":1562403591109},{"symbol":"LFC","name":"中国人寿","type":0,"remark":"","exchange":"NYSE","created":1562403591109},{"symbol":"SH600036","name":"XD招商银","type":11,"remark":"","exchange":"SH","created":1562403591109},{"symbol":"SH601155","name":"新城控股","type":11,"remark":"","exchange":"SH","created":1562403591109},{"symbol":"SZ000002","name":"万科A","type":11,"remark":"","exchange":"SZ","created":1562403591109},{"symbol":"SZ000858","name":"五粮液","type":11,"remark":"","exchange":"SZ","created":1562403591109}]},"error_code":0,"error_description":""}

建议同学先自己思考,再看答案。

从下面的代码可以看到,在get方法中传入了几个dict,分别是params,headers和cookies。

6 课堂提问回答

在霍格沃兹测试学院直播课上,有学员提出了一些问题,这里作出解答。

  • 学员:接口测试会用之后,除了发送成功/失败的正常流程外,是否跟功能测试一样,也需要设计用例场景?

  • 回答:你会发现,我们对数据的处理也要使用断言,比如验证category的值是不是1,所以,接口测试不止简单的验证成功和失败,也需要设计结果断言。

  • 学员:能对比下jmeter和requests吗,jmeter是否可以替代requests?

  • 回答:jemeter并没有大家想象这般完美,它不是独行侠,一般要和junit配合,这一点就不如Requests。

  • 请问一下思寒老师, 怎样才能达到测试专家的级别?

  • 回答:你不仅要学习完霍格沃兹测试学院的所有课程, 还要做好作业,听懂而不是听。思寒老师还提到:新手最大的问题是不看源代码和官方文档,本次教学加入了阅读源码和官文,带领大家学习。并且,后面会讲到微信小程序的测试,具体内容请关注霍格沃兹测试学院。

7 写在最后

用Requests真的很方便,这也印证了官网的开头语:equests is the only Non-GMO HTTP library for
Python,、safe for human consumption。

它们的官方文档也写的非常生动,建议大家阅读官文以了解更多使用。此外,Requests依赖于urllib3。 更多内容请关注霍格沃兹测试学院。

往期精彩:

接口测试该怎么做?持证上岗的Charles,可以帮你做什么?

工具在接口测试中发挥什么样的作用?

测试开发系列课第十期招生啦~

- 今日互动 -


欢迎文章下方留言并分享给其他测试小伙伴哦~


(别忘了 长按 加小助手微信:ihorgwarts001

回复“ 第十期 ”即可入群交流哦~)

来霍格沃兹测试开发学社,学习更多软件测试与测试开发的进阶技术,知识点涵盖web自动化测试 app自动化测试、接口自动化测试、测试框架、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移、测试右移、精准测试、测试平台开发、测试管理等内容,课程技术涵盖bash、pytest、junit、selenium、appium、postman、requests、httprunner、jmeter、jenkins、docker、k8s、elk、sonarqube、jacoco、jvm-sandbox等相关技术,全面提升测试开发工程师的技术实力
QQ交流群:484590337
公众号 TestingStudio
点击获取更多信息

posted @ 2022-01-18 09:16  霍格沃兹测试开发学社  阅读(52)  评论(0编辑  收藏  举报