接口测试之requests+pytest
1. 什么接口?
常见的接口种类:
系统内部服务层之间的接口调用,比如后端服务应用层调用service层的接口,service层掉用DAO层的接口,这个地方的接口测试属性白盒范畴,一般开发自己做就可以了
服务之间的接口调用,比如你有两个服务,一个是用户中心,一个是订单中心,订单中心会去调用户中心的服务,查询用户信息,这些接口我们一般是要测试的
系统之间的接口调用,比如你商户系统会去调公共服务系统的接口
2. 怎么开展接口测试?
流程如下4步:需求确定之后开发API文档;拿到API文档,编写接口测试用例;开发交付;实施接口测试
关注点:接口参数输入确认与错误;接口参数缺失,接口参数边界值;接口参数类型
3. 常见的requests请求
get、post、put和delete
import requests
requests.get(url,params=None,**kwargs)
requests.post(url,data=None,json=None,**kwargs)
requests.put(url,data=None,**kwargs)
requests.delete(url,**kwargs)
使用post时,然后传参是raw类型,即json数据,则使用json参数;如果传参是form_data、x-www-from-urlencoded和binary类型,都是用data类型
示例:百度搜索宫水三叶
import requests
class TestApi:
def test_search(self):
url = 'http://www.baidu.com'
params = {
'wd':'宫水三叶'
}
res = requests.get(url=url,params=params)
print(res) #<Response [200]>
if __name__ == '__main__':
TestApi().test_search()
4. 统一的requests请求及自动化关联cookie
import requests
#统一的requests请求方式
requests.request(method,url,**kwargs)
#自动关联cookie的resquest
session = requests.session()
method表示上述提到的requests四大请求中的一个
kwargs参数的介绍:
常用:params=None:get请求传参
data=None:post或者put请求传参
headers=None:请求头
json=None:post请求传参
cookies=None:Cookie
files=None:文件上传,传输时不是直接传输文件,而是传输二进制字节流,如requests.post(url,files={'file':open('文件路径','rb)})
不常用:auth=None:鉴权
timeout=None:超时处理
allow_redirects=True:是否允许重定向
proxies=None:设置代理
hooks=None:钩子
stream=None:文件下载
verify=None:证书验证
cert=None:CA证书
5. 接收响应
发送请求就有相应,由requests对象来接收
import requests
res = requests.get(url)
print(res.text) #返回文本信息
print(res.json()) #返回json格式
print(res.content) #返回字节内容
print(res.stat_code) #返回状态码(默认)
print(res.reason) #返回状态信息
print(res.cookies) #返回cookie
print(res.encoding) #返回编码格式
print(res.headers) #返回响应头
print(res.request.请求数据) #返回请求数据
6. http请求和响应
请求:请求方式,请求路径,请求参数,请求头
响应:响应码,响应信息,响应内容,响应头
7. 接口自动化实现接口关联的三种方式及提取变量的两种方式?
实现接口关联的三种方式:
通过类变量保存中间变量实现接口关联
通过单独的文件保存中间变量实现接口关联
极限封装成和工具一样,只需通过表达式就可以实现接口关联
提取变量的两种方式:
正则表达式提取(适用于提取文本结果)
re.search(匹配规则,内容):提取一个值,通过下标取值
re.findall(匹配规则,内容):提取多个值,通过下标取值
import re
s = 'https://www.baidu.com/s?wd=%E5%AE%AB%E6%B0%B4%E4%B8%89%E5%8F%B6&rsv_spt=1&rsv_iqid=0xf9c1f4d5004488bf&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=0&rsv_dl=tb&rsv_t=2d3f8MFdVICYaPChAacKXFbqtbQWljpENk54NQDbvzPRHb%2FtgB9PID%2FZXO9yZGAWo%2F58&oq=%25E5%25AE%25AB%25E6%25B0%25B4%25E4%25B8%2589%25E5%258F%25B6&rsv_pq=cd0d607200026660&rsv_btype=t&prefixsug=%25E5%25AE%25AB%25E6%25B0%25B4%25E4%25B8%2589%25E5%258F%25B6&rsp=8&inputT=15918&rsv_sug4=18202&rsv_sug=1'
res = re.search('wd=(.*?)&',s)
print(res) #<re.Match object; span=(24, 64), match='wd=%E5%AE%AB%E6%B0%B4%E4%B8%89%E5%8F%B6&'>
print(res.group(1)) #%E5%AE%AB%E6%B0%B4%E4%B8%89%E5%8F%B6
Jsonpath提取(适用于提取json结果):返回的是一个列表
jsonpath表达式规则:$表示根节点
.表示子节点
..表示递归取子节点
当提取json数据时,可能用于unicode编码问题,显示是编码之后的内容,因此需要还原
import jsonpath
res = jsonpath.jsonpath(jsondata,表达式)
#还原
json.loads(json.dumps(res.json()).replace('\\\\','\\'))
8. 统一请求封装
为了在不同操作之间保持cookie关联,因此封装一个统一请求方式,之后每次请求调佣该方式即可
import requests
class RequestUtil:
session = requests.session()
def all_send_request(self,**kwargs):
res = RequestUtil.session.request(**kwargs)
return res
9. pytest用例管理框架作用
找到用例:
模块名必须以test_开头或者_test结尾
类名必须以Test开头,并且不能有init方法
用例方法必须以test开头
执行用例
判断结果
生成报告
10. pytest常用插件
pytest-html:简单的html报告
pytest-xdist:多线程执行
pytest-ordering:控制用例的执行顺序
pytest-rerunfailures:失败用例重跑
pytest-base-url:设置基础路径
allure-pytest:生成allure报告
11. pytest运行
可以选在在命令行,即终端直接输入pytest运行,也可以创建一个main函数
#file.name=run.py
import pytest
if __name__=='__main__':
pytest.main()
12. pytest全局配置文件pytest.ini
[pytest]
#命令行参数
#常见:--html=./reports/report.html --reruns 2
addopts = -vs -m "user_manager or smoke"
#配置执行的用例位置
testpaths = ./testcase
#配置修改默认的模块规则
python_files = test_*.py
#配置修改默认的类规则
python_classes = Test*
#配置修改默认的用例规则
python_functions = test_*
#配置基础路径
base_url=http://www.baidu.com
#标记
markers =
smoke:冒烟测试用例
user_manager:用例管理
#标记markers采用@装饰器的方式添加到测试用例前
如果运行时报错,可以根据该网址进行修改:Pytest报错:UnicodeDecodeError_pytest运行报错unicodedecodeerror: 'utf-8' codec can't -CSDN博客
13. fixture插件使用
@pytest.fixture(scope='范围',autouse='自动执行',params='参数化',ids='参数名',name='插件别名')
scope范围:函数function、类class、模块module、会话session
auto自动执行:当设置为True时,无需在相应地方应用该插件,设置为False时需要
import pytest
import requests
#当autouse为False时
@pytest.fixture(scope='function',autouse=False)
def cur_stat():
print('执行前')
yield
print('执行后')
class TestApi:
def test_search(self,cur_stat):
url = 'http://www.baidu.com'
params = {
'wd':'宫水三叶'
}
res = requests.get(url=url,params=params)
res = requests.get(url=url)
print(res) #<Response [200]>
#当autouse为True时
@pytest.fixture(scope='function',autouse=True)
def cur_stat():
print('执行前')
yield
print('执行后')
class TestApi:
def test_search(self):
url = 'http://www.baidu.com'
params = {
'wd':'宫水三叶'
}
res = requests.get(url=url,params=params)
res = requests.get(url=url)
print(res) #<Response [200]>
if __name__ == '__main__':
TestApi().test_search()
params和ids可以结合使用,需要注意的是,当使用时,def的 () 中需要加上request,并且 yield也需要产生参数,同时,需要早在test函数中加入插件名
import requests
import pytest
@pytest.fixture(scope='function',autouse=False,params=['宫水三叶','宫水四叶'],ids=['3','4'])
def cur_stat(request):
print('执行前')
yield request.param
print('执行后')
class TestApi:
def test_search(self,cur_stat):
print(cur_stat)
url = 'http://www.baidu.com'
params = {
'wd': cur_stat
}
res = requests.get(url=url,params=params)
print(res) #<Response [200]>
if __name__ == '__main__':
TestApi().test_search()
name相当于python中 import requests as rs,即重命名的过程
14. fixture结合conftest.py 文件实现前后置
可以将前后置内容,放置conftest.py文件中来维护,conftest.py文件会自动从外层到内层执行
import pytest
@pytest.fixture(scope='module',autouse=True)
def cur_stat():
print('执行前')
yield
print('执行后')
15. yaml文件读取与写入
可以把一下跨文件的数据保存在yaml文件中,这样就可以跨文件调用了
import yaml
def write_yaml(data):
with open('./extract.yaml',encoding='utf-8',mode='a+') as f:
yaml.dump(data,stream=f,allow_unicode=True)
def read_yaml(key):
with open('./extract.yaml',encoding='utf-8',mode='r') as f:
d = yaml.load(stream=f,Loader=yaml.FullLoader)
return d[key]
def clear_yaml():
with open('./extract.yaml',encoding='utf-8',mode='r') as f:
f.truncate()
16. pytest的数据驱动
通过修改数据从而去驱动测试用例的执行,从而得到不同的结果。当只有一组数据时,只会执行一次用例,多组数据则执行多次。
pytest数据驱动装饰器
@pytest.mark.parametrize('参数名',参数值)
import requests
import pytest
from CSDN.requestlearn.yaml_util import read_testdata
class TestApi:
@pytest.mark.parametrize('testdata',read_testdata(path))
def test_search(self,testdata):
# url = 'http://www.baidu.com'
# params = {
# 'wd': '宫水三叶'
# }
url = testdata['request']['url']
params = testdata['request']['params']
res = requests.get(url=url,params=params)
print(res) #<Response [200]>
if __name__ == '__main__':
TestApi().test_search()
17. Allure测试报告生成
配置pytest.ini文件
addopts = -vs --alluredir=./temps --clean-alluredir
在run.py文件中进行配置
import pytest
import os
import time
if __name__ == '__main__':
pytest.main()
time.sleep(3)
os.system('allure generate ./temps -o ./reports --clean')
更多推荐

所有评论(0)