最新要闻
- 高亮度+顶级芯 旗舰更进一步!当贝X5激光投影仪评测:2450CVIA带来震撼视觉体验
- 焦点速递!免费、不用注册、支持中文!ChatGPT最强竞品爆火:一手实测体验在此
- 快报:国产FPS《边境》发布之路坎坷:服务器出现紧急BUG
- 五一火车票明日开售:五一假期连休5天
- 世界新动态:徕卡味儿十足!小米13 Ultra摄影套装亮相:手机秒变相机
- 山东省高级人民法院电话簿(山东省高级人民法院电话)
- 世界热文:DXO拍照得分全球第一!OPPO Find X6 Pro卖疯 销量同比增长129%
- 世界快资讯丨失业大军涌入外卖 骑手收入腰斩:拼了一天赚400 却被罚1000
- 上亿广场里排队20分钟等餐?为了这一幕,新市府已经等了三年
- 天天亮点!大二男生靠打工奖学金穷游37城:没问家里要过1分钱
- 焦点热门:准备好钱包 比亚迪百万豪车仰望U8四天后开售:超跑U9一同亮相
- Redmi Note 12 Turbo首销过后还在狂卖!卢伟冰都没想到
- 变化极大的iOS 17要来了!苹果内测iOS 16.6系统:或为绝唱更新
- 今年五一档杀疯了 16部国产大片扎堆:好莱坞大片中国市场遇冷 不符合国人审美
- 世界看热讯:签约!年产45万吨,林州林钢将建亚洲单体最大铸管生产车间
- 世界微速讯:2023年百大影响力人物:马斯克、TikTok周受资等入榜
广告
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
全球微动态丨python 之 session鉴权的处理
【资料图】
一、session鉴权的处理
1. requests的会话对象
就像一个浏览器一样,它会在同一个会话中自动处理cookie信息,不需要写任何额外的代码。
import requests
session = requests.Session() # 理解为就是一个浏览器
type(session)
requests.sessions.Session
session.post()# 登录session.get() # 获取某个数据,会自动携带上一步收到的cookie
# 课堂派案例headers = {"cookie": "FZ_STROAGE.ketangpai.com=eyJTRUVTSU9OSUQiOiIzMTI5MjRiNTU2MzNmMDUxIiwiU0VFU0lPTkRBVEUiOjE2Mzk1NzA0NDQ3Njd9; ARK_ID=undefined; ketangpai_home_slb=3fbda3fc94d5d1be63720d9c156288d0; PHPSESSID=kmugv5id4lcecie33asikt3p96; ketangpai_home_remember=think%3A%7B%22username%22%3A%22MDAwMDAwMDAwMLV2x5eHz7dthN523LWtftmC0IDak4NubQ%22%2C%22expire%22%3A%22MDAwMDAwMDAwMLOGvd6IubtrhKiGl7G2dZ4%22%2C%22token%22%3A%22MDAwMDAwMDAwMMurrpWavLehhs1-lbO5hZWEzYfcepuomcWmmqaMiHtnr5ypzYWosKKZq6HQxtOK0ZCme5p-q6iZu2yrn4uNhJ3KedDYk7ivboS4jt6zuY2Ug6eDl36KYW0%22%2C%22sign%22%3A%2207f1bd0c97817e6d7ebe92bfe8e30fe9%22%7D", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"}res = requests.get(url="https://v4.ketangpai.com/UserApi/getUserInfo")
res.status_code
200
res.cookies
res.json()
{"status": 0, "info": "您还未登陆!"}
session = requests.Session() # 1. 创建一个session对象
# 2. 登录login_url = "https://v4.ketangpai.com/UserApi/login"data = {"email": "877***9301@qq.com", "password": "Pyt***inlan", "remember": 0}# json data paramsresponse = session.post(url=login_url, data=data)
session.cookies
res = session.get(url="https://v4.ketangpai.com/UserApi/getUserInfo")
res.json()
{"status": 1, "data": {"id": "MDAwMDAwMDAwMLSGz96Iqb9phLVyoQ", "username": "****", "avatar": "http://v4.ketangpai.com/Public/Common/img/40/26.png", "usertype": "1", "email": "877***01@qq.com", "stno": "", "atteststate": 0, "attestInfo": []}}
# 如果不用session对象,每一步都需要自己处理cookie
login_url = "https://v4.ketangpai.com/UserApi/login"data = {"email": 877***9301@qq.com", "password": "Pyt***inlan", "remember": 0}# 1.登录response = requests.post(url=login_url, data=data)
response.status_code
200
response.json()
{"status": 1, "url": "/Main/index.html", "token": "MDAwMDAwMDAwMMurrpWavLehhs1-lbO5hZWEzYfcepuomcWmmqaMiHtnr5ypzYWosKKZq6HQxtOK0ZCme5p-haiZu2yrn4uNhJ3KedDYk7ivboS4jt6zuY2Ug7d33n96YW0", "isenterprise": 0, "uid": "MDAwMDAwMDAwMLSGz96Iqb9phLVyoQ"}
# 2.获取数据res = requests.get(url="https://v4.ketangpai.com/UserApi/getUserInfo", cookies=response.cookies)
res.json()
{"status": 1, "data": {"id": "MDAwMDAwMDAwMLSGz96Iqb9phLVyoQ", "username": "****", "avatar": "http://v4.ketangpai.com/Public/Common/img/40/26.png", "usertype": "1", "email": "877***01@qq.com", "stno": "", "atteststate": 0, "attestInfo": []}}
requests库的session对象仅仅只是自动帮我们处理了cookie的携带问题。
2. 封装处理session鉴权的http请求函数
思路:
- 保证在一个会话中使用同一个会话对象即可
- 给每一个用例类创建一个会话对象即可。
import jsonimport unittestfrom jsonpath import jsonpathimport settingfrom common import logger, dbfrom common.data_handler import ( replace_args_by_re, generate_no_usr_phone)from common.encrypt_handler import generate_signimport requestsclass BaseCase(unittest.TestCase): """ 用例基类 """ db = db logger = logger setting = setting name = "base_case" session = requests.session() # 创建一个session对象用来处理session鉴权 @classmethod def setUpClass(cls) -> None: cls.logger.info("==========={}接口开始测试===========".format(cls.name)) @classmethod def tearDownClass(cls) -> None: cls.logger.info("==========={}接口结束测试===========".format(cls.name)) def flow(self, item): """ 测试流程 """ self.logger.info(">>>>>>>用例{}开始执行>>>>>>>>".format(item["title"])) # 把测试数据绑定到方法属性case上,其他也要把一些变量绑定到对象的属性上 self._case = item # 1. 处理测试数据 self.process_test() # 2. 发送请求 self.send_request() # 3. 断言 self.assert_all() def process_test(self): """ 测试数据的处理 """ # 1.1 生成测试数据 self.generate_test_data() # 1.2 替换依赖参数 self.replace_args() # 1.3 处理url self.process_url() # 1.4 鉴权处理 self.auth_process() def auth_process(self): """ v3版本鉴权处理 :return: """ request_data = self._case.get("request_data") if request_data: headers = request_data.get("headers") if headers: if headers.get("X-Lemonban-Media-Type") == "lemonban.v3": # 获取token token = self._case["request_data"]["headers"]["Authorization"].split(" ")[-1] # 生成签名 sign, timestamp = generate_sign(token, self.setting.SERVER_RSA_PUB_KEY) # 添加到请求数据中 self._case["request_data"]["json"]["sign"] = sign self._case["request_data"]["json"]["timestamp"] = timestamp # if self._case["request_data"]["headers"]["X-Lemonban-Media-Type"] == "lemonban.v3": # # 获取token # token = self._case["request_data"]["headers"]["Authorization"].split(" ")[-1] # # 生成签名 # sign, timestamp = generate_sign(token, self.setting.SERVER_RSA_PUB_KEY) # # 添加到请求数据中 # self._case["request_data"]["json"]["sign"] = sign # self._case["request_data"]["json"]["timestamp"] = timestamp def generate_test_data(self): """ 生成测试数据 """ """ 生成测试数据,不是固定流程,有不同可以复写 :return: """ self._case = json.dumps(self._case) if "$phone_number$" in self._case: phone = generate_no_usr_phone() self._case = self._case.replace("$phone_number$", phone) self._case = json.loads(self._case) def replace_args(self): """ 替换参数 """ self._case = json.dumps(self._case) # 把用例数据dumps成字符串,一次替换 self._case = replace_args_by_re(self._case, self) self._case = json.loads(self._case) # 再将request_data, expect_data loads为字典 try: self._case["request_data"] = json.loads(self._case["request_data"]) self._case["expect_data"] = json.loads(self._case["expect_data"]) except Exception as e: self.logger.error("{}用例的测试数据格式不正确".format(self._case["title"])) raise e def process_url(self): """ 处理url """ if self._case["url"].startswith("http"): # 是否是全地址 pass elif self._case["url"].startswith("/"): # 是否是短地址 self._case["url"] = self.setting.PROJECT_HOST + self._case["url"] else: # 接口名称 try: self._case["url"] = self.setting.INTERFACES[self._case["url"]] except Exception as e: self.logger.error("接口名称:{}不存在".format(self._case["url"])) raise e def send_request(self): """ 发送请求 @return: """ self._response = self.session.request( url=self._case["url"], method=self._case["method"], **self._case["request_data"]) # self._response = send_http_request(url=self._case["url"], method=self._case["method"], # **self._case["request_data"]) def assert_all(self): try: # 3.1 断言响应状态码 self.assert_status_code() # 3.2 断言响应数据 self.assert_response() # 响应结果断言成功后就提取依赖数据 self.extract_data() # 3.3 数据库断言后面的任务 self.assert_sql() except Exception as e: self.logger.error("++++++用例{}测试失败".format(self._case["title"])) raise e else: self.logger.info("<<<<<<<<<用例{}测试成功<<<<<<<".format(self._case["title"])) def assert_status_code(self): """ 断言响应状态码 """ try: self.assertEqual(self._case["status_code"], self._response.status_code) except AssertionError as e: self.logger.warning("用例【{}】响应状态码断言异常".format(self._case["title"])) raise e else: self.logger.info("用例【{}】响应状态码断言成功".format(self._case["title"])) def assert_response(self): """ 断言响应数据 """ if self._case["res_type"].lower() == "json": res = self._response.json() elif self._case["res_type"].lower() == "html": # 扩展思路 res = self._response.text try: self.assertEqual(self._case["expect_data"], {"code": res["code"], "msg": res["msg"]}) except AssertionError as e: self.logger.warning("用例【{}】响应数据断言异常".format(self._case["title"])) self.logger.warning("用例【{}】期望结果为:{}".format(self._case["title"], self._case["expect_data"])) self.logger.warning("用例【{}】的响应结果:{}".format(self._case["title"], res)) raise e else: self.logger.info("用例【{}】响应数据断言成功".format(self._case["title"])) def assert_sql(self): """ 断言数据库 """ if self._case.get("sql"): # 返回指定键的值,如果键不在字典中返回默认值 None 或者设置的默认值。 # 只有sql字段有sql的才需要校验数据库 # 只有sql字段有sql的才需要校验数据库 sqls = self._case["sql"].split(",") for sql in sqls: try: self.assertTrue(self.db.exist(sql)) except AssertionError as e: self.logger.warning("用例【{}】数据库断言异常,执行的sql为:{}".format(self._case["title"], sql)) raise e except Exception as e: self.logger.warning("用例【{}】数据库断言异常,执行的sql为:{}".format(self._case["title"], sql)) raise e def extract_data(self): """ 根据提取表达式提取对应的数据 :return: """ if self._case.get("extract"): if self._case["res_type"].lower() == "json": self.extract_data_from_json() elif self._case["res_type"].lower() == "html": self.extract_data_from_html() elif self._case["res_type"].lower() == "xml": self.extract_data_from_xml() else: raise ValueError("res_type类型不正确,只支持json,html,xml") def extract_data_from_json(self): """ 从json数据中提取数据并绑定到类属性中 :return: """ try: rules = json.loads(self._case.get("extract")) except Exception as e: raise ValueError("用例【{}】的extract字段数据:{}格式不正确".format(self._case["title"], self._case["extract"])) for rule in rules: # 类属性名 name = rule[0] # 提取表达式 exp = rule[1] # 根据jsonpath去响应中提取值 value = jsonpath(self._response.json(), exp) # 如果能提取到值 if value: # 把值绑定到对应的类属性上 setattr(self.__class__, name, value[0]) # 注意value是个列表 else: # 提取不到值,说明jsonpath写错了,或者是响应又问题 raise ValueError("用例【{}】的提取表达式{}提取不到数据".format(self._case["title"], self._case["extract"])) def extract_data_from_html(self): """ 从html数据中提取数据并绑定到类属性中 :return: """ raise ValueError("请实现此方法") def extract_data_from_xml(self): """ 从xml数据中提取数据并绑定到类属性中 :return: """ raise ValueError("请实现此方法")
from unittestreport import ddt, list_datafrom common.base_case import BaseCasecases = [ {"title": "课堂派登录", "method": "post", "url": "https://v4.ketangpai.com/UserApi/login", "request_data": "{"data": {"email": "877***01@qq.com", "password": "Pyt***inlan", "remember": 0}}", "status_code": 200, "res_type": "json", "expect_data": "{"status": 1}" }, { "title": "获取用户信息", "method": "get", "url": "https://v4.ketangpai.com/UserApi/getUserInfo", "request_data": "{}", "status_code": 200, "res_type": "json", "expect_data": "{"status": 1}" }]@ddtclass TestCourseFlow(BaseCase): name = "课堂派测试" @list_data(cases) def test_course(self, item): self.flow(item) def assert_response(self): """ 复写assert_response方法实现课堂派的断言 :return: """ if self._case["res_type"].lower() == "json": res = self._response.json() elif self._case["res_type"].lower() == "html": # 扩展思路 res = self._response.text try: self.assertEqual(self._case["expect_data"], {"status": res["status"]}) except AssertionError as e: self.logger.warning("用例【{}】响应数据断言异常".format(self._case["title"])) self.logger.warning("用例【{}】期望结果为:{}".format(self._case["title"], self._case["expect_data"])) self.logger.warning("用例【{}】的响应结果:{}".format(self._case["title"], res)) raise e else: self.logger.info("用例【{}】响应数据断言成功".format(self._case["title"]))if __name__ == "__main__": BaseCase.unittest.main()
关键词:
-
【世界播资讯】git中 commit 和 pull 的先后顺序问题会产生多余的merge记录
commit和pull的先后顺序问题最近提交代码,发现一个问题。自己很清楚的记得本次的提交是没有进行合并的...
来源: -
全球微资讯!#POWERBI 度量值动态格式字符串,利用动态格式,实现百分数智能缩位(powerbi4月重磅更新功能)
以下内容(基于POWERBI23年4月更新的最新版本)实际业务中,日常报表一般都有一个较为规范的百分数缩位...
来源: 全球微动态丨python 之 session鉴权的处理
【世界播资讯】git中 commit 和 pull 的先后顺序问题会产生多余的merge记录
全球微资讯!#POWERBI 度量值动态格式字符串,利用动态格式,实现百分数智能缩位(powerbi4月重磅更新功能)
高亮度+顶级芯 旗舰更进一步!当贝X5激光投影仪评测:2450CVIA带来震撼视觉体验
焦点速递!免费、不用注册、支持中文!ChatGPT最强竞品爆火:一手实测体验在此
快报:国产FPS《边境》发布之路坎坷:服务器出现紧急BUG
五一火车票明日开售:五一假期连休5天
世界新动态:徕卡味儿十足!小米13 Ultra摄影套装亮相:手机秒变相机
山东省高级人民法院电话簿(山东省高级人民法院电话)
当前报道:全面解析反欺诈(羊毛盾)API,助你识别各类欺诈风险
天天实时:T-SQL基础教程Day2
世界热文:DXO拍照得分全球第一!OPPO Find X6 Pro卖疯 销量同比增长129%
世界快资讯丨失业大军涌入外卖 骑手收入腰斩:拼了一天赚400 却被罚1000
上亿广场里排队20分钟等餐?为了这一幕,新市府已经等了三年
.NET7使用HttpClient实现查询天气预报接口
天天亮点!大二男生靠打工奖学金穷游37城:没问家里要过1分钱
焦点热门:准备好钱包 比亚迪百万豪车仰望U8四天后开售:超跑U9一同亮相
Redmi Note 12 Turbo首销过后还在狂卖!卢伟冰都没想到
变化极大的iOS 17要来了!苹果内测iOS 16.6系统:或为绝唱更新
今年五一档杀疯了 16部国产大片扎堆:好莱坞大片中国市场遇冷 不符合国人审美
世界看热讯:签约!年产45万吨,林州林钢将建亚洲单体最大铸管生产车间
世界时讯:SpringBoot 如何保证接口安全?老鸟们都是这么玩的
全面数字化时代,国有大型银行如何走好金融创新之路?
速讯:PHP 备忘清单_开发速查表分享
今日热议:如何快速开发软件?这篇文章说明白了
世界微速讯:2023年百大影响力人物:马斯克、TikTok周受资等入榜
公司回应员工未及时回复收到被辞退:顶撞领导 不服从管理
【全球时快讯】量旋科技进军超导量子计算!三大新品、软硬件全流程搞定
世界最资讯丨3年前老机型没被抛弃!一加8系列官宣适配ColorOS 13.1
男子机动车道上骑鸵鸟还拍视频炫耀:系养殖基地训练师、已被处理
世界百事通!16岁女孩骑摩托载21岁女伴不幸遇难,生前网友曾劝“危险”被怼
ntuser是什么文件?ntuser文件可以删除吗?
宏基笔记本电脑风扇设置在哪里?宏基笔记本电脑风扇声音大怎么解决?
摩托罗拉xt685什么时候上市的?摩托罗拉xt685手机参数
显卡金手指是什么?显卡金手指磨损有影响吗?
266.58显卡驱动没法识别硬件是怎么回事?266.58显卡驱动没法识别硬件怎么解决?
全球快报:更安全、更低耗的微服务架构改造之道
PDCA循环模型——如何用同样的时间做更多的事?【No.1 】
聚焦:山西焦化:公司2023年第一季度报告预约披露时间为2023年4月25日
世界关注:荣耀推“三叉戟” 赵明:笔记本过去30年没啥变化 需要跃迁
【全球新要闻】比理想L8 Air便宜3万多 魏牌蓝山四驱版值得买吗?一文看懂
240Hz高刷屏+RTX40显卡!微星星影15游戏图赏
【独家焦点】今年五一档“杀疯了” 至少16部影片扎堆上映:《长空之王》最受期待
黑白相机卖到71000元!徕卡M11 Monochrom正式发布
Espanso文本拓展软件使用体验
当前时讯:简单的了解下 Fetch API 的工作原理
详解 APISIX Lua 动态调试插件 inspect
四舍五入 - 逼疯全世界的开发者
全球热议:NTP网络校时服务器(北斗GPS校时器)在地铁内网系统中的应用
【新视野】半导体设备板块快速走高,金海通涨停
年内公募新基金发行突破2800亿元 债券型基金占比超六成
《Redfall》引发粉丝强烈不满
环球焦点!《名侦探柯南》新剧场版上映 柯哀亲了登顶热搜!新兰CP党表示要弃剧
上海车展全球首发 比亚迪B级纯电SUV官宣:命名“宋L”
焦点快看:女子团购住民宿 结果住到自己家的房子 网友:王思聪有这体验
【全球快播报】荣耀Magic5成旗舰标杆!赵明:从来没有友商敢挑战它的续航、屏幕
环球速看:中标 | 含塔筒3200-3438元/kW!海装、金风、电气风电预中标山东能源渤中海上风电项目
Spring Boot 接口加解密,新姿势来了!
全球微头条丨苹果iPhone 15 Pro机型再曝光:依然实体音量键 静音拨片改为Action按钮
苹果和安卓折腾了5年 愣是干不过微信小程序
抢先看!迪士尼更新真人版《小美人鱼》预告:黑小美人鱼海下展唯美瞬间
世界看热讯:标致408保价期内降价遭集体投诉 车主:4S店称地方补贴不算降价
【全球聚看点】现场办公面对面听意见解难题 西固区定制化服务助企纾困
天天微动态丨【读财报】消费主题基金年报透视:2022年净值普跌 全年共亏逾280亿
每日热门:清华、北大在校生五一淄博免费游”?官方回应:消息属实
快讯:巴奴“天价土豆”换名后重新上架:多地售价18元一份 北京上海22元
云南16岁女孩载21岁女孩无证驾驶摩托车身亡 生前网友曾劝危险
天天观热点:张朝阳建议年轻人多做饭、早上6点就起:外卖都是垃圾!王石唱反调
全球微头条丨问界M5系列华为高阶智驾版来了:不惧鬼探头 实现泊车“自由”
读SQL进阶教程笔记11_关系数据库基础
天天实时:从消博会透视中国消费活力
每日快播:美股财报季拉开前夕美银泼冷水:美企盈利将从“糟糕”走向“更糟”
【天天报资讯】沙特俄罗斯产油国联手减产 国际油价飙升:美国难受 补充战略石油储备
【世界新要闻】女性同事过生日送什么花
环球快讯:ASP.NET Core MVC 从入门到精通之路由
全国4亿人集体“吃土”?沙尘暴持续下该如何保命
当前动态:都江堰商业街现多只红嘴相思鸟尸体:专家判断系撞玻璃死亡
世界聚焦:菜花蛇、眼镜王蛇、王蛇:谁才真正的毒蛇之王?
【播资讯】国产科幻FPS《边境》Steam褒贬不一:UI稀烂 错误频出
天天速递!微星RTX 4070魔龙深度测试:老黄的刀法太精准了!
环球时讯:老两口搬家花4万,这么多年过去了,搜索引擎“搬家刺客”依然存在?
废弃矿井地下水中多环芳烃的降解与迁移机理
1811 E Living Sequence 两种解法
ChatGPT进化,人性消失,究竟是好是坏?
每日聚焦:第137篇:重学ES6模块化
天天热门:容器操作,应用部署,迁移与备份,Dockerfile
焦点快播:20亿的交易被华为反对 没任何可能合作 诺基亚坚持要卖鼎桥母公司股权
黄仁勋主持 台北电脑展NVIDIA发布会敲定!RTX 4060 Ti/4060要来了
焦点消息!《塞尔达传说:王国之泪》终极预告发布:短发公主绝美 盖侬真身登场
天天微资讯!仿真-定向耦合器
今日报丨java 处理常量字符串过长 & springboot 项目读取 resouces 文件夹下的文件内容
ORACLE还原恢复启动时数据库报ORA-00704, ORA-00604, ORA-00904
世界速读:linux环境下安装Docker
世界关注:百度松果菁英班--oj赛(第二次)
面试题百日百刷-kafka篇(三)
速讯:AMD发布RDNA3架构Radeon Pro W7000系列专业显卡:AI性能提升2.7倍、满血3999美元
天天播报:比“500万内最好的SUV”更好!魏牌蓝山上市:27.38万元起
当前聚焦:纯白机身美翻了!影驰RTX 4070星曜OC图赏
为什么今年沙尘暴突然这么严重?40多年植树造林白干了?
环球播报:79888元!大疆Inspire 3发布:全画幅8K电影无人机