当你乘坐火车的时候,你不会想到一个30000mA(111Wh)的充电宝突然无法带上车了,你会不会生气呢?最新的铁路携带物品规定于7月开始实施,充电宝最多携带两个,每个额定容量不超过100Wh,也就是27000mA,所以过安检会让你要么寄快递,要么让别人来拿,要么留下,反正你是带不上火车的,要是你强行带走,可能警察也会强行把你带走。吃一点长一智,所以每次出行乘坐交通工具时,先看一看携带物品是否可以上车,充电宝、打火机、压缩性气体罐装物品如喷雾、香水、酒等等,不然非常影响你的出行,当然开车不需要考虑这些问题。说到底,还是没钱,还是要努力学习啊。
这次总结的是(三)接口自动化测试-Python自带Requests+Unittest框架,此Python库是一款非常好用的脚本工具,毕竟Python语言容易上手,所以使用Python编写脚本进行测试也是非常方便的。
CSDN话题挑战赛第2期
参赛话题:学习笔记
一、Requests简介
1、不同测试方式区别
工具
手写脚本
灵活性差
灵活性高
操作简单
需要一定的编程能力
用于较为单一的接口测试
用于业务连续的接口测试
** 2、Python特点**
(1)简单 (2)高级 (3)面向对象 (4)可扩展 (5)免费和开源 (6)边编译边执行 (7)可移植 (8)丰富的库
3、Requests库的简介
(1)官方文档:urllib.request --- 用于打开 URL 的可扩展库 — Python 3.10.7 文档 (2)Requests是唯一的一个非转基因的Python HTTP库,可以安全享用。 (3)特点 Keep-Alive&连接池 国际化域名和URL 带持久Cookies的会话 浏览器式的SSL认证 自动内容解码 Unicode响应体 文件分块上传、下载 流下载 连接超时 分块请求
二、Requests常用函数
1、环境搭建
(1)非Python自带库,需单独安装
windows→pip install requests、easy_install requests、或者pycharm中安装 linux→sudo pip install requests
2、常用函数
(1)requests.request() #构造一个请求,支持以下各种方法
(2)requests.get() #获取html的主要方法(至少有一个参数-接口地址、有返回值的方法。返回值就是本次请求的服务器响应结果)
(3)requests.post() #向html网页提交post请求的方法
(4)requests.head() #获取html头部信息的主要方法
(5)requests.put() #向html提交put请求的方法
(6)requests.patch() #向html提交局部修改的请求
(7)requests.delete() #向html提交删除请求
3、基本语法格式
(1)Response常用属性
(2)r.status_code #http请求的返回状态,若为200则表示请求成功
(3)r.text #http响应内容的字符串形式,即返回的页面内容
(4)r.recoding #从http header中猜测的相应内容编码方式
(5)r.rapparent_encoding #从内容中分析处的响应内容编码方式(备选)
(6)r.content #http响应内容的二进制形式
三、Requests用于接口测试
1、不带参数的GET请求
(1)发送不带参数的GET请求requests.get("url") (2)获取和输出各种响应值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/19 8:25
# software: PyCharm
"""get请求"""
# (1)导入requests包
import requests
import json
# (2)构造一个不带参数的get请求
response = requests.get("http://www.baidu.com")
print(f"本次响应数据类型是{type(response)}")
# (3)输出本次响应的状态码
print(f"\n\n本次响应状态码数据类型是{type(response.status_code)}")
print(f"本次响应状态码是{response.status_code}")
# (4)输出本次响应的所有文本
print(f"\n\n本次响应文本数据类型是{type(response.text)}")
response.encoding = "utf-8"
print(f"本次响应文本是{response.text}")
# (5)输出本次响应的所有值
print(f"\n\n本次响应cookies数据类型是{type(response.cookies)}")
response.encoding = "utf-8"
print(f"本次响应网站的Cookies是{response.cookies}")
# (6)判断:本次请求后,服务器响应返回的字符串中,是否有“百度一下,你就知道”
exp = "百度一下,你就知道"
if exp in response.text:
print(f"\n\n响应值中包含你希望的字符串:{exp}。")
else:
print("\n\n响应值中不包含你希望的字符串。")
2、带参数的GET请求
(1)发送带参数的GET请求requests.get("url", ****params****=params) (2)获取和输出各种响应值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/19 8:25
# software: PyCharm
"""get请求"""
# (1)导入requests包
import requests
import json
# (2)构造一个不带参数的get请求、带参数的get请求、带参数的post请求
get_parameter = {
"q": "apple",
"from": "en",
"to": "zh",
"appid": "xxx",
"salt": "202002121503",
"sign": "7105f811ca9d3835146ed9c44ab46770",
}
response1 = requests.get("https://fanyi-api.baidu.com/api/trans/vip/translate", params=get_parameter)
print(f"\n本次响应数据类型是{type(response1)}")
# (3)输出本次响应的状态码
print(f"\n本次响应状态码数据类型是{type(response1.status_code)}")
print(f"本次响应状态码是{response1.status_code}")
# (4)输出本次响应的所有文本
print(f"\n本次响应文本数据类型是{type(response1.text)}")
response1.encoding = "utf-8"
print(f"本次响应文本是{response1.text}")
# (5)输出本次响应的所有值
print(f"\n本次响应cookies数据类型是{type(response1.cookies)}")
response1.encoding = "utf-8"
print(f"本次响应网站的Cookies是{response1.cookies}")
# (6)判断:本次请求后,服务器响应返回的字符串中,是否有“百度一下,你就知道”
exp = "apple"
if exp in response1.text:
print(f"\n响应值中包含你希望的字符串:{exp}。")
else:
print("\n响应值中不包含你希望的字符串。")
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/19 10:33
# software: PyCharm
"""
使用Python加requests库方式实现:输入一个字符串,通过百度翻译接口,输出其中文翻译内容
技术点:
(1)输入函数input
(2)get请求
(3)带参数(构造数据:随机数函数random、加密函数MD5)
appid-xxx、密钥-zzz
(4)字符串的拼接
(5)字符编码的转换(输入字符串必须转化为utf-8)
(6)只输出翻译结即可(apple-苹果)
(7)使用函数的方式调用
"""
import hashlib
from random import randint
import requests
# 设定字符编码格式
encoding = "utf-8"
def get_md5(content):
"""MD5加密函数"""
# 获取一个MD5加密算法对象
md = hashlib.md5()
# 对字符串编码转化为“utf-8”,否则会报TypeError: Unicode-objects must be encoded before hashing
md.update(content.encode(encoding))
# 返回加密后的16进制字符串
return md.hexdigest()
def test_baidu_input():
"""百度翻译函数"""
# 定义接口URL
url = "https://fanyi-api.baidu.com/api/trans/vip/translate"
# 定义APPID
app_id = "xxx"
# 定义密钥secretkey
secret_key = "zzz"
# 定义随机数salt,直接转换为字符串
salt = str(randint(100000, 999999))
print(f"salt:{salt}")
# 定义被翻译的字符串q
q = input("请输入你要翻译的内容:")
# 定义源语言from=auto,翻译语言to=zh
tr_from = "auto"
tr_to = "zh"
# 加密字符串拼接
splicing_sign = app_id + q + salt + secret_key
sign = get_md5(splicing_sign)
print(f"sign:{sign}")
# 构造参数
data = {"q": q, "from": tr_from, "to": tr_to, "appid": app_id, "salt": salt, "sign": sign}
# 构造get请求
res = requests.get(url, params=data)
# 响应结果JSON格式化:res.json()等同于json.load(res.text)
result = res.json()
tr_res = result["trans_result"][0]["dst"]
print(f"翻译结果:{tr_res}")
test_baidu_input()
3、带参数的POST请求
(1)发送带参数的POST请求requests.get("url", ****data****=params)(等同于以字典的形式提交form表单数据) (2)获取和输出各种响应值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/19 8:25
# software: PyCharm
"""get请求"""
# (1)导入requests包
import requests
import json
# (2)构造一个不带参数的get请求、带参数的get请求、带参数的post请求
post_parameter = {
"q": "apple",
"from": "en",
"to": "zh",
"appid": "xxx",
"salt": "202002121503",
"sign": "7105f811ca9d3835146ed9c44ab46770",
"Content-Type": "application/x-www-form-urlencoded",
}
response2 = requests.post("https://fanyi-api.baidu.com/api/trans/vip/translate", data=post_parameter)
print(f"\n本次响应数据类型是{type(response2)}")
# (3)输出本次响应的状态码
print(f"\n本次响应状态码数据类型是{type(response2.status_code)}")
print(f"本次响应状态码是{response2.status_code}")
# (4)输出本次响应的所有文本
print(f"\n本次响应文本数据类型是{type(response2.text)}")
response2.encoding = "utf-8"
print(f"本次响应文本是{response2.text}")
# (5)输出本次响应的所有值
print(f"\n本次响应cookies数据类型是{type(response2.cookies)}")
response2.encoding = "utf-8"
print(f"本次响应网站的Cookies是{response2.cookies}")
# (6)判断:本次请求后,服务器响应返回的字符串中,是否有“百度一下,你就知道”
exp = "苹果"
if exp in response2.text:
print(f"\n响应值中包含你希望的字符串:{exp}。")
else:
print("\n响应值中不包含你希望的字符串。")
4、响应结果转换为JSON格式
**** response.json()****等同于json.loads(response.text)
# (1)导入requests包
import requests
import json
get_parameter = {
"q": "apple",
"from": "en",
"to": "zh",
"appid": "20200211000382774",
"salt": "202002121503",
"sign": "7105f811ca9d3835146ed9c44ab46770",
}
response1 = requests.get("https://fanyi-api.baidu.com/api/trans/vip/translate", params=get_parameter)
print(type(response1.json()), response1.json())
print(response1.json()["error_msg"], json.loads(response1.text))
四、Requests库综合应用
1、融入unittest框架
(1)unittest工作原理
unittest:****单元测试框架****,作为自动化测试框架的用例组织执行框架 核心:****TestCase测试用例****(每个测试方法都是****test开头****、setUp()初始化、tearDown销毁)、****TestSuite测试套件****、TestRunner测试运行器、TestLoader测试用例加载器、Fixture 内容:编写web自动化-webdriver、编写接口自动化-requests请求、编写移动端自动化-python+appium+unittest
(2)unittest主要结构
**** 创建测试类****(继承unittest.TestCase类)
**** 编写测试用例****
**** 定义测试套件****(流程unittest.TestSuite())
**** 加载测试用例****
**** 创建测试报告****(HTMLTestRunner)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/20 9:41
# software: PyCharm
"""
快速搭建unittest框架:
(1)创建测试类
"""
import unittest
import requests
class TestV2ex(unittest.TestCase):
"""定义一个测试类,继承unittest.TestCase类"""
def setUp(self) -> None:
"""初始化方法"""
print("初始化属性")
def tearDown(self) -> None:
"""定义结束方法"""
print("所有用例执行结束")
def test_hot(self):
"""自定义测试方法"""
# driver = webdriver.Firefox()
def test_node(self):
"""自定义测试方法"""
res = requests.get("http://www.baidu.com")
return res
def test_user(self):
"""自定义测试方法"""
a = 1
b = 2
self.assertEqual(a, b)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/20 12:22
# software: PyCharm
"""
快速搭建unittest框架:
(2)编写测试用例
(3)定义测试套件(流程)
(4)加载测试用例
(5)创建测试报告:使用unittest框架内容HTMLTestRunner导出HTML格式的测试报告
"""
import unittest
from HTTPTestRunner import HTMLTestRunner
from unittest_api import TestV2ex
# 构建测试套件(流程)
testsuite = unittest.TestSuite()
# 加载测试用例
testsuite.addTest(TestV2ex("test_hot"))
testsuite.addTest(TestV2ex("test_node"))
testsuite.addTest(TestV2ex("test_user"))
# 创建测试报告
fp = open('./report.html', 'wb') # wb:以二进制的格式写入
"""
HTMLTestRunner:
(1)https://pypi.python.org/pypi/HTMLTestRunner
(2)python下的Lib目录,新建一个HTMLTestRunner.py文件,把内容直接复制进去并修改
第94行,将import StringIO修改成import io
第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
第766行,将uo = o.decode(‘latin-1’)修改成uo = e
第772行,将ue = e.decode(‘latin-1’)修改成ue = e
第631行,将print >> sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime)修改
成print(sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime))
"""
# stream:文件信息流;title:报告的标题;description:一般写对于测试环境的描述信息(操作系统、浏览器……);tester:测试人员
runner = HTMLTestRunner(stream=fp, title='测试报告', description='执行报告')
runner.run(testsuite)
fp.close()
2、参数化和断言
(1)使用CSV外部文件
参数化: 程序中(代码本身:random、list、range) 外部数据文件(CSV文件、text文件)
(2)断言
自带断言方法
assertEqual(a, b) a==b
assertNotEqual(a, b) a!=b
assertTrue(x) bool(x) is True
assertFalse(x) booI(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a,b)
assertNotIsInstance(a, b) not isinstance(a,b)
自写判断进行结果输出
if-else
try-except-finally异常捕获
3、输出测试报告和测试日志
(1)测试报告
框架内容-HTMLTestRunner(python2,修改内容可在python3中使用) 导出HTML格式的测试报告 runner = HTMLTestRunner(stream=fp, title='测试报告', description='执行报告')
# 创建测试报告
fp = open('./report.html', 'wb') # wb:以二进制的格式写入
"""
HTMLTestRunner:
(1)https://pypi.python.org/pypi/HTMLTestRunner
(2)python下的Lib目录,新建一个HTMLTestRunner.py文件,把内容直接复制进去并修改
第94行,将import StringIO修改成import io
第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
第766行,将uo = o.decode(‘latin-1’)修改成uo = e
第772行,将ue = e.decode(‘latin-1’)修改成ue = e
第631行,将print >> sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime)修改
成print(sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime))
"""
# stream:文件信息流;title:报告的标题;description:一般写对于测试环境的描述信息(操作系统、浏览器……);tester:测试人员
runner = HTMLTestRunner(stream=fp, title='测试报告', description='执行报告')
runner.run(testsuite)
fp.close()
(2)日志
APP---adb
adb logcat #打印默认日志数据
adb logcat -v time :e --pid=<pid> >D:\log.txt #打印详细时间(-v time)、级别是Error(:e)和给定pid中(--pid=<pid>)的日志数据并保存到电脑固定位置
Linux---查看系统运行日志 生成日志(标准化格式:程序员按企业设计输出系统运行信息) 用途:系统运行异常时查看异常信息(用户名、时间和日期、操作事件、操作对象、操作内容、信息级别显示(info/warning/error/exception))
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/8/20 12:21
# software: PyCharm
"""测试日志输出"""
import time
info_type = 3
def log():
"""以标准格式输出一些脚本运行过程中的重要信息"""
fp = open('./log.txt', 'a+')
# 运行时间记录:年月日时分秒
e_t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(e_t)
# 获取当前运行的文件名和函数名
f_n = log.__name__
print(f_n)
# 模拟信息类型的判断
# msg_type = "info"
if info_type == 0:
msg_type = "info"
elif info_type == 1:
msg_type = "warning"
elif info_type == 2:
msg_type = "error"
else:
msg_type = "exception"
# 组织一条写入log.txt的信息
info = f"[{e_t}][{msg_type}]:{f_n}\n"
# 将info写入log
fp.write(info)
fp.close()
log()
log.txt日志文件
[2022-08-20 12:47:10][info]:log [2022-08-20 12:47:14][warning]:log [2022-08-20 12:47:17][error]:log [2022-08-20 12:47:20][exception]:log [2022-09-07 16:37:17][exception]:log [2022-09-07 16:37:54][exception]:log
五、测试代码和运行结果
1、测试代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/27 18:15
# software: PyCharm
"""
1、使用unittest框架
2、定义请求方法
3、在方法中完成请求
4、对返回值进行JSON格式化
5、对格式化后的数据进行类型(字典、列表)判断
6、对接口数据进行断言
7、将日志信息进行组合写入日志文件
"""
import time
import unittest
import requests
class TestV2ex(unittest.TestCase):
"""对v2ex网站进行测试"""
def setUp(self) -> None:
"""初始化测试环境"""
def test_hot(self):
"""对热点话题接口进行测试"""
# 定义函数开始时间
start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
# URL地址
url = "https://www.v2ex.com/api/topics/hot.json"
# 发送请求
res = requests.get(url)
# JSON格式化响应结果
result = res.json()
# 定义表示返回值中数据元素个数的变量
res_num = 0
# 判断数据类型,确定元素个数
res_type = type(result)
if isinstance(result, dict):
res_num = 1
elif isinstance(result, list):
res_num = len(result)
else:
print("无该数据类型")
# 预期结果
except_num = 10
# 断言
try:
self.assertEqual(except_num, res_num, "个数不一样!!!")
except AssertionError as ae:
print(ae)
finally:
# 定义函数结束时间
end_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
# 组合日志信息
log_info = f"start_time:{start_time}|res_type:{res_type}|res_num:{res_num}|end_time:{end_time}"
# 输出测试日志
with open("./log/log.txt", "a+", encoding="utf-8") as f:
f.write(log_info)
f.write("\n")
def tearDown(self) -> None:
"""重置测试环境"""
if __name__ == '__main__':
unittest.main()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/27 18:15
# software: PyCharm
"""
快速搭建unittest框架:
(2)编写测试用例
(3)定义测试套件(流程)
(4)加载测试用例
(5)创建测试报告:使用unittest框架内容HTMLTestRunner导出HTML格式的测试报告
HTMLTestRunner:
(1)https://pypi.python.org/pypi/HTMLTestRunner
(2)python下的Lib目录,新建一个HTMLTestRunner.py文件,把内容直接复制进去并修改
第94行,将import StringIO修改成import io
第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
第766行,将uo = o.decode(‘latin-1’)修改成uo = e
第772行,将ue = e.decode(‘latin-1’)修改成ue = e
第631行,将print >> sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime)修改
成print(sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime))
"""
import time
import unittest
from HTTPTestRunner import HTMLTestRunner
from test_case import TestV2ex
# 构建测试套件(流程)
test_suite = unittest.TestSuite()
# 加载测试用例
test_suite.addTest(TestV2ex("test_hot"))
# 创建测试报告
f_t = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
filename = f"./result/{f_t}.html"
with open(filename, "wb") as f:
"""wb:以二进制的格式写入"""
# stream:文件信息流;title:报告的标题;description:一般写对于测试环境的描述信息(操作系统、浏览器……);tester:测试人员
runner = HTMLTestRunner(stream=f, title='测试报告', description='执行报告')
runner.run(test_suite)
2、运行结果
愿你我都能为中华民族的伟大复兴尽一份绵薄力量,让中华文化的根扎根在中国这片绿水青山之上,让新一代中华儿女传承与发扬!!!
---无名之辈
以上内容均是本人自学,当然是有网上公布的内容,如有冒犯,请留言,立即改正,谢谢!
看完要是觉得对自己有用,动一下您那根金色的会一指禅的右手食指,按一下您的鼠标左键,在对应的那个位置点个赞,亦或者在评论区留下您的绝顶好句,亦或者收藏在您的收藏夹里,再走也不迟嘛!您说要不要得!谢谢您的阅读和赞赏!
版权归原作者 bigbear_001 所有, 如有侵权,请联系我们删除。