欢迎光临
我们一直在努力

Python-Pytest-Requests-API接口测试自动化框架2

一、

    1.基于工具类的:
    (1)postman+newman+jenkins
    (2)jmeter+ant+jenkins
    (3)apifox+apifox-cli+jenkins
    2.基于框架和平台:
        python+requests+pytest+allure+yaml+logging+jenkins
    3.开发自动化测试平台

二、常见请求–Request请求部分

    1.get
    (1)def get(url,params=None, **kwargs)
        url:接口地址
        params:参数,在get请求的url后面传的参数
        **kwargs:可变长度的字典
    (2)**kwargs 是 “关键字参数(keyword arguments)” 的缩写,作用是接收函数调用时传入的「多余的关键字参数」,并把它们打包成一个字典。

import jsonpath
import requests

# **kwargs 是 “关键字参数(keyword arguments)” 的缩写,
# 作用是接收函数调用时传入的「多余的关键字参数」,
# 并把它们打包成一个字典。

class TestApi:

# 获取access_token鉴权码接口
def test_get_token(self):
urls="https://api.weixin.qq.com/cgi-bin/token"
datas={
"grant_type":"client_credential",
"appid":"wx8a9de038e93f77ab",
"secret":"8326fc915928dee3165720c910effb86"
}
res=requests.get(url=urls, params=datas)
# list=jsonpath.jsonpath(res.json(),'$.access_token') # 接口关联方式一:jsonpath提取实现接口关联
# print(list[0])
token=res.json()['access_token']
print(token)
print(res.json())

# 查询标签接口
# def test_select_flag(self):
# urls = "https://api.weixin.qq.com/cgi-bin/tags/get"
# datas={
# "access_token": "???"
# }
# res=requests.get(url=urls, params=datas)
# print(res.json())

if __name__ == '__main__':
# TestApi().test_select_flag()
test_obj = TestApi()
# 1. 先执行test_get_token,获取并保存access_token
test_obj.test_get_token()
# 2. 再执行test_select_flag,这时就能拿到access_token了
# test_obj.test_select_flag()

    2.def post(url,data=None,json=None,**kwargs):0
        url:接口地址>
        data:参数(表单/表格—x-www-form-urlencoded)
        json:参数(JSON—application/json)  –请求头
        **kwargs:可变长度的字典
    3.def put(url, data=None,**kwargs):
    4.def delete(url,**kwargs):
    5.四种方法底层都调用的是request方法
    (1)requests.request("get",url,params=params,**kwargs)
    (2)requests.request()调用的是session.request方法            session.request(method=method, url=url,**kwargs, —最底层方法    —接口自动化所用
    (3)requests.request与session.request的区别?
            requests.request的每个请求是独立的,而session.request会自动关联所有请求的cookie信息

    5.Postman四种传参方式:
    (1)form-data:既有表单,又有文件上传
            requests中对应files
    (2)x-www-form-urlencoded: 纯表单
            requests中对应data
    (3)raw:传json格式的参数   json:application/json
            requests中对应json
    (4)binary:传二进制文件—转换为二进制再上传  application/octrent-stream
            requests中对应data

三、Request响应部分

    1.常见的返回信息
    (1)res .text
    (2)res.json()返回字典形式的结果
    (3)res.content 返回字节类型的结果
    (4)res.status_code返回状态码
    (5)res.reason  返回状态信息
    (6)res.cookie 返回cookie信息
    (7)res.encoding 返回编码格式
    (8)res.headers 返回响应头
    (9)res.request.xxx 得到请求数据
    2.接口关联的三种层次:
    (1)通过类变量保存中间变量实现接口关联 –可能会有不同用例(.py文件)的相互调用,而形成递归

"""
通过类变量,保存中间变量,实现接口关联
"""
import requests

class TestApi:
# 接口关联的三种层次:(1)通过类变量保存中间变量实现接口关联
access_token="" # 类变量,是一个全局变量,可以在下面的用例(test_select_flag)去执行
# 获取access_token鉴权码接口
def test_get_token(self):
urls="https://api.weixin.qq.com/cgi-bin/token"
datas={
"grant_type":"client_credential",
"appid":"wx8a9de038e93f77ab",
"secret":"8326fc915928dee3165720c910effb86"
}
res=requests.get(url=urls, params=datas) # get请求,通过params传参
TestApi.access_token=res.json()['access_token']
print(TestApi.access_token)
# 查询标签接口
def test_select_flag(self):
urls = "https://api.weixin.qq.com/cgi-bin/tags/get"
datas={
"access_token": TestApi.access_token
}
res=requests.get(url=urls, params=datas)
print(res.json())

# 编辑标签接口,–post 传递json格式数据
def test_edit_flag(self):
urls = "https://api.weixin.qq.com/cgi-bin/tags/update" # url跟在路径后,用params传 –实际是**kwargs里的params
datas1={
"access_token": TestApi.access_token
}
datas2={
"tag":{"id":134,"name":"广东人"}
}
res=requests.post(url=urls, json=datas2, params=datas1)
print(res.json())

# 或者让token跟在后面,也可以成功传递
# def test_edit_flag(self):
# urls = "https://api.weixin.qq.com/cgi-bin/tags/update?access_token="+TestApi.access_token # url跟在路径后,用params传 –实际是**kwargs里的params
#
# datas2={
# "tag":{"id":134,"name":"广东人"}
# }
# res=requests.post(url=urls, json=datas2)
# print(res.json())

# 文件上传-files 参数类型 data
def test_file_upload(self):
urls = "https://api.weixin.qq.com/cgi-bin/media/uploadimg" # url跟在路径后,用params传 –实际是**kwargs里的params
datas1={
"access_token": TestApi.access_token
}
datas2={
"media":open(r"D:\\相册\\图片\\2.jpg","rb") # rb 只读 二进制
}
res=requests.post(url=urls, files=datas2, params=datas1)
print(res.json())

if __name__ == '__main__':
test_obj = TestApi()
test_obj.test_get_token()
# 2. 再执行test_select_flag,这时就能拿到access_token了
test_obj.test_select_flag()
# 3.编辑
test_obj.test_edit_flag() # 这里要求错误码为0;即错误码为0代表测试通过
#4.文件上传
test_obj.test_file_upload()

"""
通过类变量,保存中间变量,实现接口关联
"""
import requests
from commons.requests_util import RequestsUtil

class TestApi:
# 接口关联的三种层次:(1)通过类变量保存中间变量实现接口关联
access_token="" # 类变量,是一个全局变量,可以在下面的用例(test_select_flag)去执行
# 获取access_token鉴权码接口
def test_get_token(self):
urls="https://api.weixin.qq.com/cgi-bin/token"
datas={
"grant_type":"client_credential",
"appid":"wx8a9de038e93f77ab",
"secret":"8326fc915928dee3165720c910effb86"
}
res=RequestsUtil().send_all_request(method="get",url=urls,params=datas) # get请求,通过params传参
TestApi.access_token=res.json()['access_token']
print(TestApi.access_token)
# 查询标签接口
def test_select_flag(self):
urls = "https://api.weixin.qq.com/cgi-bin/tags/get"
datas={
"access_token": TestApi.access_token
}
res=RequestsUtil().send_all_request(method="get",url=urls, params=datas)
print(res.json())

# 编辑标签接口,–post 传递json格式数据
def test_edit_flag(self):
urls = "https://api.weixin.qq.com/cgi-bin/tags/update" # url跟在路径后,用params传 –实际是**kwargs里的params
datas1={
"access_token": TestApi.access_token
}
datas2={
"tag":{"id":134,"name":"广东人"}
}
res=RequestsUtil().send_all_request(method="post",url=urls, json=datas2, params=datas1)
print(res.json())

# 或者让token跟在后面,也可以成功传递
# def test_edit_flag(self):
# urls = "https://api.weixin.qq.com/cgi-bin/tags/update?access_token="+TestApi.access_token # url跟在路径后,用params传 –实际是**kwargs里的params
#
# datas2={
# "tag":{"id":134,"name":"广东人"}
# }
# res=requests.post(url=urls, json=datas2)
# print(res.json())

# 文件上传-files 参数类型 data
def test_file_upload(self):
urls = "https://api.weixin.qq.com/cgi-bin/media/uploadimg" # url跟在路径后,用params传 –实际是**kwargs里的params
datas1={
"access_token": TestApi.access_token
}
datas2={
"media":open(r"D:\\相册\\图片\\2.jpg","rb") # rb 只读 二进制
}
res=RequestsUtil().send_all_request(method="post",url=urls, files=datas2, params=datas1)
print(res.json())

if __name__ == '__main__':
test_obj = TestApi()
test_obj.test_get_token()
# 2. 再执行test_select_flag,这时就能拿到access_token了
test_obj.test_select_flag()
# 3.编辑
test_obj.test_edit_flag() # 这里要求错误码为0;即错误码为0代表测试通过
#4.文件上传
test_obj.test_file_upload()

    (2)通过单独的文件保存中间变量实现接口关联。     —封装
    (3)极限封装成零代码的方式实现接口关联。
    3.接口关联两种方式:
        (1)正则提取实现接口关联
            re.seach()通过正则匹配一个值,通过下标[1]取值,没有匹配到返回None
            re.findall()通过正则匹配多个值,返回List,通过下标取值,没有匹配到返回None
    (2)JsonPath提取实现接口关联
            jsonpath.jsonpath()返回一个列表,通过下标取值,没有找到返回None
    4.re.search()
    (1)re.search()的 .group(1) 是用来提取正则表达式中第一个括号分组匹配到的内容,是Python正则模块中获取分组结果的核心用法。
     (2)re.search(pattern, string) :在字符串中搜索符合正则表达式 pattern 的内容,返回一个 Match 对象(匹配到结果时)或 None (未匹配到)。
    (3) 括号 () 在正则中的作用:表示分组,会把括号内匹配到的内容单独保存,方便后续提取。
     (4)group(1) 的含义:
             group(0) (或直接 group() ):返回整个正则表达式匹配到的完整内容。
             group(1) :返回第一个括号分组匹配到的内容。
            若有多个分组(如 (a)(b) ),则 group(2) 返回第二个分组内容,以此类推。
    如:TestApi3.csrf_token=re.search('name="csrf_token" value="(.*?)"',res.text).group(1) 
    表达式里只有一组(),也就是(.*?),这就是第一个括号分组
    (5)如果正则写成: (name)="csrf_token" (value)="(.*?)" ,就有三个括号分组:
             第一个分组: (name)  →  group(1) 提取 name 
            第二个分组: (value)  →  group(2) 提取 value 
             第三个分组: (.*?)  →  group(3) 提取 csrf_token 值

四、接口自动化测试框架的封装(统一请求的封装)

    1.进行统一请求封装的原因
    (1)去除重复冗余的代码
    (2)实现统一的异常处理以及日志监控
    2.先封装,再写用例

五、用例管理框架pytest

    1.作用:
    (1)发现用例:默认发现用例的规则
        模块名必须|以test 开头或者 test结尾。
        测试类必须以Test开头。
        测试方法必须以test 开头
    (2)执行用例
    (3)判断结果
    (4)生成报告
    2.
    (1)可以结合selenium,requests,appium,实现web,接口,app自动化
    (2)可以结合Allure生成美观的报告,可以结合jenkins实现持续集成
    (3)丰富的插件
    3.插件
    (1)pytest
    (2)pytest-html  生成pytest报告
    (3)pytest-xdist 多线程执行
    (4)pytest-ordering 控制用例的执行顺序
    (5)pytest-returnfailures 失败用例重跑
    (6)pytest-base-url  基础路径(测试环境、开发环境、生产环境)
    (7)allure-pytest 生成allure报告
    把这些放在requirements.txt文件里,一次性安装
    pip install -r requirements.txt

"""
通过类变量,保存中间变量,实现接口关联
"""
import pytest

from commons.requests_util import RequestsUtil

# fixture固件 False :不自动执行;想让哪个函数使用,将connection_mysql作为参数传入
@pytest.fixture(scope='function',autouse=False,params=["mysql","redis"]) # 指定作用范围 –函数
def connection_mysql(request): # 加参数request 可以把参数 params[]里的内容打印

print("连接数据库…") # 每个函数之前执行

# 通过yield 唤醒后置
yield request.param # 两个参数 mysql redis 用例会执行两次
print("关闭数据库连接")

class TestApi:

# 接口关联的三种层次:(1)通过类变量保存中间变量实现接口关联
access_token="" # 类变量,是一个全局变量,可以在下面的用例(test_select_flag)去执行

# # 在用例之前、之后进行某些操作
# def setup_method(self):
# print("—–每个用例之前的操作—–")
#
# def teardown_method(self):
# print("—–每个用例之后的操作—–")
#
# # 每个类之前、之后的操作
# def setup_class(self):
# print("*****每个类之前的操作*****")
#
# def teardown_class(self):
# print("*****每个类之后的操作*****")

# 获取access_token鉴权码接口
# 标记为冒烟测试
@pytest.mark.smoke
def test_get_token(self,base_url,connection_mysql):
print(connection_mysql)
urls=base_url+"/cgi-bin/token"
datas={
"grant_type":"client_credential",
"appid":"wx8a9de038e93f77ab",
"secret":"8326fc915928dee3165720c910effb86"
}
res=RequestsUtil().send_all_request(method="get",url=urls,params=datas) # get请求,通过params传参
TestApi.access_token=res.json()['access_token']
print(TestApi.access_token)

# 查询标签接口
# 标记为 用户管理
@pytest.mark.user
def test_select_flag(self):
urls = "https://api.weixin.qq.com/cgi-bin/tags/get"
datas={
"access_token": TestApi.access_token
}
res=RequestsUtil().send_all_request(method="get",url=urls, params=datas)
print(res.json())

# 编辑标签接口,–post 传递json格式数据
def test_edit_flag(self):
urls = "https://api.weixin.qq.com/cgi-bin/tags/update" # url跟在路径后,用params传 –实际是**kwargs里的params
datas1={
"access_token": TestApi.access_token
}
datas2={
"tag":{"id":134,"name":"广东人"}
}
res=RequestsUtil().send_all_request(method="post",url=urls, json=datas2, params=datas1)
print(res.json())

    4.Pytest用例管理框架执行方式—三种
    (1)命令行
    (2)主函数
    (3)通过配置文件(pytest.ini)来改变以及执行用例
    (4)命令行方式、主函数方式,都会读取pytest.ini配置文件

    六、Pytest用例管理框架的前后置(固件/夹具)    

    1.
    (1)可以在 用例之前、用例之后,做一些操作 setup teardown  使用少
    (2)一般使用 fixture 固件
    (3)fixture是一个装饰器,可装饰函数和类  
    @pytest.fixture(scope="作用域",params="参数化",autouse="是否自动执行",ids="参数别名",name="装饰器/夹具别名")
    2.fixture参数解释:
    (1)scope:funciton class moudle seesion(整个会话作用于)
    (2)autouse : true 和 false
    (3)params : 参数化 
            params=["mysql","redis"]  参数有几个,用例就执行几次
        需要使用request参数 和yield   
        request.params
    3.fixture 夹具,就是在用例(类 模块 会话)之前和之后做一些操作

三、接口关联封装(基于一个独立的YAML文件)

        1.yaml_util类

# yaml 工具类
import os

import yaml

# 1.写入(追加写入 a+)
def write_yaml(data):
with open(os.getcwd()+"/extract.yaml", encoding="utf-8",mode="a+") as f:
# stream=f 输出流 f 是open的文件
# allow_unicode=True 允许yaml输出中保留Unicode字符(如中文)避免转义导致乱码
yaml.dump(data,stream=f,allow_unicode=True) # 写入

# 2.读取
def read_yaml(key):
with open(os.getcwd()+"/extract.yaml", encoding="utf-8",mode="r") as f:
# FullLoader 安全加载器 解析f 中的yaml内容,拒绝执行任意Python代码
value=yaml.load(f,yaml.FullLoader)
return value[key]

# 3.清空
def clean_yaml():
with open(os.getcwd()+"/extract.yaml", encoding="utf-8",mode="w") as f:
f.truncate() # 清空

赞(0)
未经允许不得转载:171主机测评 » Python-Pytest-Requests-API接口测试自动化框架2
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址