系列文章目录
Day01 软件测试基础总结
Day02 测试用例知识点总结(上)
Day03 测试用例知识点总结(下)
Day04 禅道-从安装到卸载
Day05 MySql的基础使用
Day06 MySql知识点总结
Day07 MySql知识点再总结与多表查询
Day08 redis的基础知识
Day08 VMware的安装、Linux系统安装和Linux基础命令
Day09 Linux常用命令总结
Day10 Linux环境部署和项目构建
Day11 shell脚本基础知识
Day12 接口和协议
Day13 Postman的使用
Day13 Windows环境下的JDK安装与Tomcat的启动
Day14 jenkins部署
Day15 jenkins的简单使用
Day16 charles的基本使用
Day17 考试
Day18 考试
Day19 Fiddler的简单使用
Day20 Python基础
Day21 python 语句基础
Day22 Python数据类型(上)
Day23 Python数据类型(下)
Day24 Python函数
Day25 Python的文件操作和异常处理
Day26 Python面向对象
Day27 Python的部分算法
Day28 单元测试 unittest
Day29 单元测试 pytest
Day30 接口测试requests
目录
前言
requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到,Requests是Python语言的第三方的库,专门用于发送HTTP请求
一、requests基本使用
request是第三方模块,所以需要下载
pip install requests
1.get与post请求方式
注意:传参数中get与post方式的第一个参数都是url,但是第二个参数,前者是params后者是data
import unittest,requests
class TestAPIClass(unittest.TestCase):
def test_get_noparam(self):
result=requests.get('http://www.baidu.com')
def test_get(self):
result=requests.get(url='http://127.0.0.1:8080/pinter/com/getSku',params={'id':1})
print(result.json())
def test_post(self):
result = requests.post(url='http://127.0.0.1:8080/pinter/com/login', data={'userName':'admin','password':'1234'})
print(result.json())
if __name__ == '__main__':
unittest.main()
'''
{'code': '0', 'message': 'success', 'data': {'skuId': 1, 'skuName': 'ptest-1', 'price': '459', 'stock': 951, 'brand': 'testfan'}}
Ran 3 tests in 0.050s
OK
{'code': '0', 'message': 'success', 'data': None}
Process finished with exit code 0
'''
补充的方法:
Requests响应:(result是上述代码中的局部变量)
result.status_code 响应状态码
result.heards 响应头
result.cookies 响应cookies
result.text 响应文本
result.json() 响应的字典类型数据
result. encoding 当前编码
result. content 以字节形式(二进制)返回
requests方法:
1:添加等待时间
requests.get(url,timeout=1) #超过等待时间则报错
2:添加请求头信息
requests.get(url,headers=headers) #设置请求头
3:添加文件files = {'file': open('report.xls', 'rb')}
requests.post(url, files=files) #添加文件
二、读取文件流程
1.使用unittest模块csv文件传递
数据
url,param,method,assert
http://apis.juhe.cn/mobile/get,"{""phone"": ""13429667914"",""key"": ""444f03c0884efb00ce17e98ade1ce2c2""}",get,0
http://apis.juhe.cn/mobile/get,"{""phone"": ""1"",""key"": ""444f03c0884efb00ce17e98ade1ce2c2""}",get,201102
http://apis.juhe.cn/mobile/get,"{""phone"": ""13429667914"",""key"": ""444f03c0884efb00ce17e98ade1ce2a2""}",get,10001
http://apis.juhe.cn/mobile/get,"{""phone"": ""13429667914"",""key"": ""444f03c0884efb00ce17e98ade1ce2c2""}",post,0
读取数据,最后的切片是去除表头
import csv
class ReadCsvClass():
def readCsvMethod(self):
file=csv.reader(open('../data/test001.csv'))
item=[i for i in file][1::]
return item
测试用例,csv格式会将字典变为字符串,需要eval()方法转换为字典
import unittest,requests
from readdata.readdata import ReadCsvClass
r=ReadCsvClass()
a=r.readCsvMethod()
class TestCsvClass(unittest.TestCase):
def test_001(self):
for i in a:
if i[2]=='get':
r=requests.get(i[0],eval(i[1])).json()['error_code']
self.assertEqual(r,int(i[3]))
else:
r = requests.post(i[0], eval(i[1])).json()['error_code']
self.assertEqual(r, int(i[3]))
if __name__ == '__main__':
unittest.main()
'''
Process finished with exit code 0
Ran 1 test in 0.562s
OK
'''
2.使用pytest模块xlsx文件传递数据
场景:使用聚合数据中的手机号归属地
数据
读取数据,表格中可能存在多张表,使用load_workbook选择那张表
from openpyxl import load_workbook
class ReadExcle():
def read_excel(self):
#打开表
wb = load_workbook('../data/test002.xlsx')
sheet = wb["Sheet1"]
# print(sheet.max_row) # 行
# print(sheet.max_column) # 列
test_data = [] # 把所有行的数据放到列表中
for i in range(2,sheet.max_row+1): #控制行数
sub_data = {} # 把每行的数据放到字典中
for j in range(1,sheet.max_column+1):
sub_data[sheet.cell(1,j).value] = sheet.cell(i,j).value
test_data.append(sub_data) # 拼接每行单元格的数据
return test_data
# if __name__ == '__main__':
# r =ReadExcle()
# print(r.read_excel())
读取数据读取的结果展示(输出为一行,为了展示效果,手动分行),可以看出是包含在列表中的字典,其中params的值是字符串中的字典,注意使用时使用eval()方法将字符串转成字典
测试用例
import requests,pytest
from readdata.readdataxlsx import ReadExcle
r = ReadExcle()
excledata = r.read_excel()
class TestXecleClass():
def test_001(self):
for i in excledata:
if i["method"] =="get":
resultobject = requests.get(url=i["url"],params=eval(i["params"]))
assert resultobject.json()["error_code"] ==i["assert"]
else:
resultobject = requests.post(url=i["url"],data=eval(i["params"]))
assert resultobject.json()["error_code"] ==i["assert"]
if __name__ == '__main__':
pytest.main(['-s',"testexcel.py"])
'''
============================= test session starts =============================
collecting ... collected 1 item
testAPIXlSX.py::TestXecleClass::test_001
============================== 1 passed in 0.80s ==============================
Process finished with exit code 0
PASSED [100%]
'''
三、数据驱动
使用pytest
import pytest,requests
class TestDataDriverClass():
phone='13017580185'
city ='北京'
@pytest.mark.parametrize('a,b,c',[('http://apis.juhe.cn/mobile/get',
{'phone':phone,'key':'67776b2f1ef19ff7a9956323de7dc044'},
0)])
def test_PhoneMethod(self,a,b,c):
result=requests.get(a,b)
global city
city=result.json()['result']['city']
assert int(result.json()['error_code'])==int(c)
print(city)
@pytest.mark.parametrize('a,b,c',[('http://apis.juhe.cn/simpleWeather/query',
{'city':city,'key':'a08f159bbc70321908e77ac395f8f52a'},
0)])
def test_weatherMethod(self,a,b,c):
result = requests.get(a,b)
assert int(result.json()['error_code'])==int(c)
print(result.json())
print(city)
if __name__ == '__main__':
pytest.main(['-s','datadriver.py'])
'''
============================= test session starts =============================
platform win32 -- Python 3.10.6, pytest-7.1.2, pluggy-1.0.0
rootdir: C:\Users\Jing\PycharmProjects\test_requ\testcase
collected 2 items
datadriver.py 开封
.{'reason': '查询成功!', 'result': {'city': '北京', 'realtime': {'temperature': '22', 'humidity': '66', 'info': '多云', 'wid': '01', 'direct': '南风', 'power': '4级', 'aqi': '25'}, 'future': [{'date': '2022-08-29', 'temperature': '18/27℃', 'weather': '多云', 'wid': {'day': '01', 'night': '01'}, 'direct': '南风'}, {'date': '2022-08-30', 'temperature': '18/29℃', 'weather': '多云转晴', 'wid': {'day': '01', 'night': '00'}, 'direct': '西南风转北风'}, {'date': '2022-08-31', 'temperature': '17/31℃', 'weather': '晴', 'wid': {'day': '00', 'night': '00'}, 'direct': '北风'}, {'date': '2022-09-01', 'temperature': '18/29℃', 'weather': '晴转多云', 'wid': {'day': '00', 'night': '01'}, 'direct': '东北风转东南风'}, {'date': '2022-09-02', 'temperature': '18/30℃', 'weather': '多云', 'wid': {'day': '01', 'night': '01'}, 'direct': '南风'}]}, 'error_code': 0}
开封
.
============================== 2 passed in 0.55s ==============================
'''
由上面的代码可以看出数据驱动无法传值
四、接口关联
场景依旧是手机号码归属地,获得城市名查询天气预报,与数据驱动内容基本一致,不过不再是数据驱动,是直接赋值
import pytest,requests
class TestDataDriverClass():
city=''
def test_PhoneMethod(self):
result=requests.get('http://apis.juhe.cn/mobile/get',{'phone':'13017580185','key':'67776b2f1ef19ff7a9956323de7dc044'})
global city
city=result.json()['result']['city']
assert int(result.json()['error_code'])==0
print(city)
def test_weatherMethod(self):
result = requests.get('http://apis.juhe.cn/simpleWeather/query',{'city':city,'key':'a08f159bbc70321908e77ac395f8f52a'})
assert int(result.json()['error_code'])==0
print(result.json())
print(city)
if __name__ == '__main__':
pytest.main(['-s','guanlian.py'])
'''
============================= test session starts =============================
platform win32 -- Python 3.10.6, pytest-7.1.2, pluggy-1.0.0
rootdir: C:\Users\Jing\PycharmProjects\test_requ\testcase
collected 2 items
guanlian.py 开封
.{'reason': '查询成功!', 'result': {'city': '开封', 'realtime': {'temperature': '19', 'humidity': '80', 'info': '阴', 'wid': '02', 'direct': '西风', 'power': '2级', 'aqi': '36'}, 'future': [{'date': '2022-08-29', 'temperature': '16/19℃', 'weather': '小雨', 'wid': {'day': '07', 'night': '07'}, 'direct': '北风转西北风'}, {'date': '2022-08-30', 'temperature': '16/22℃', 'weather': '阴', 'wid': {'day': '02', 'night': '02'}, 'direct': '西风转西南风'}, {'date': '2022-08-31', 'temperature': '20/28℃', 'weather': '多云转阴', 'wid': {'day': '01', 'night': '02'}, 'direct': '南风转北风'}, {'date': '2022-09-01', 'temperature': '18/28℃', 'weather': '阴转多云', 'wid': {'day': '02', 'night': '01'}, 'direct': '东北风'}, {'date': '2022-09-02', 'temperature': '18/28℃', 'weather': '多云转阴', 'wid': {'day': '01', 'night': '02'}, 'direct': '东北风'}]}, 'error_code': 0}
开封
.
============================== 2 passed in 0.31s ==============================
'''
由上方代码看出,直接传值可以实现接口关联
还需注意:unittest与pytest不要同时使用,可能会出现错误的情况,如Empty suite,一般重启以下程序就可以了
总结
首先我是用python+requests+unittest+htmltestrunner/pytest+allure实现了接口自动化测试
首先在数据包中存储接口的测试数据比如csv文件,excel文件等,实现数据和代码逻辑的分离
然后在读取数据的包中实现读取文件的获取数据的操作
接着在测试用例包中导入读取数据模块,通过requests的get/post方法获取该接口的返回数据的信息在单元测试模块(unittest/pytest)中通过断言验证返回的值和预期结果是否一致
最终结果打印在html类型的测试报告中