Pytest+Yaml+Allure接口自动化框架集成
1.框架介绍
2.YAML 用例编写规范
3.YAML用例数据读取
4.核心执行器用例执行
1.框架介绍
框架的内容
关键字驱动框架
1.examples用例文件夹
yaml/excel用例(选择一种即可)
2.HAT框架代码
parse 读取yaml/excel用例数据
core 执行用例(核心执行器执行用例--本质pytest)
keywords 项目封装的操作
utils 工具类
extend 扩展的组件
context 上下文管理 管理会话(一次会话还是多次会话)
main程序入口
requirements.txt作用:
拿到这个项目目前安装了哪些库,导出来库 pip freeze >requirements.txt
给项目给别人,跑项目 txt文件 pip install -r requirements.txt -i 镜像
2.yaml用例编写规范
用例怎么写?
yaml用例--yaml规则
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- '#' 表示注释
- 列表
- :字典 :后面需要有个空格
3.读取yaml文件数据:
1.安装pyyaml库
pip install pyyaml -i 镜像
2.读取yaml数据
常识:
-
./ 同级目录
-
../上一级目录
-
../../上上级目录
-
r''是为了防止转义,比如\n \t 有自己的意思,比如空格,比如换行
4.核心执行器用例执行
目标:
如果已经拿到了yaml的数据,怎么执行登录的接口?
回答:
核心执行器执行,本质就是pytest
要安装pytest
pip install pytest==7.3.1 -i 镜像
拿到数据,调度执行yaml用例
1.拿到yaml数据后需要传给相应的接口
parse/ReadYamlCase文件
import yaml
import os
import os
print(os.getcwd())
# 获取当前文件所在文件夹的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 获取要读取的yaml文件的完整路径
yaml_path = os.path.join(current_dir, '../../examples/api-cases-yaml/test.yaml')
def readYaml(yaml_path):
case_info=[]
with open(yaml_path, 'r',encoding='utf-8') as f:
data = yaml.load(f, Loader=yaml.FullLoader)
print("yaml文件数据:", data)
case_info.append(data)
return case_info
if __name__=="__main__":
readYaml(yaml_path)
在core里面的TestRunner.py中:(核心执行器--本质是pytest)
import os
import sys
import pytest
current_directory = os.path.dirname(os.path.abspath(__file__))
hat_dir = os.path.dirname(current_directory)
sys.path.append(hat_dir)
from parse.YamlCaseParser import readYaml
print(os.getcwd())
print(current_directory)
file_path = os.path.abspath(os.path.join(current_directory, '../../examples/api-cases-yaml/test.yaml'))
print(file_path)
class TestRunner2:
data = readYaml(file_path)
# print(data)
@pytest.mark.parametrize('caseinfo',data)#把data的数据拿过来,放到caseinfo里面,一定是一个列表,然后通过parametrize会把列表去掉,变成一个裸字典
2.执行登录接口
-
在main.py中设置执行的参数以及需要执行的文件路径
-
执行 发送请求POST接口,需要四要素(url,请求方式,接口参数,响应结果)
怎么在yaml数据中找到我想要的信息:
yaml数据
用例步骤: #具体要测试的接口内容
- 发送登陆接口:
操作类型: 发送请求POST #一定要跟Keywords发请求的函数名一致
请求地址: "http://shop-xo.hctestedu.com" #加不加index.php对于这个商城项目接口都可以 如果加可以在后面加个/index.php
URL参数:
s: /api/user/login
application: app
application_client_type: weixin
请求数据:
accounts: "youyi"
pwd: "123456"
type: "username"
1.整个是个字典,我想取字典里的这个内容用例步骤 所以 step_info=caseinfo.get("用例步骤",none)
{'发送登陆接口': {'操作类型': '发送请求POST', '请求地址': 'http://shop-xo.hctestedu.com', 'URL参数': {'s': '/api/user/login', 'application': 'app', 'application_client_type': 'weixin'}, '请求数据': {'accounts': 'youyi', 'pwd': '123456', 'type': 'username'}}}
2.要取到发送的是什么接口: step_name=step_info.key()
要取到接口的所有信息: step_value=step_info.values()
dict_value{'操作类型': '发送请求POST', '请求地址': 'http://shop-xo.hctestedu.com', 'URL参数': {'s': '/api/user/login', 'application': 'app', 'application_client_type': 'weixin'}, '请求数据': {'accounts': 'youyi', 'pwd': '123456', 'type': 'username'}}
目前取到的只是字典的键对象和值对象,我需要把他转成列表,然后再取到列表中的元素
所以是step_name = list(step_info.key())[0]
step_value = list(step.values())[0]
3.实例化对象
4.找KeyWords类中是否有发送请求POST方法
若能找到-传入相应参数 找不到-抛异常
代码如下:
import os
import sys
import pytest
import requests
current_directory = os.path.dirname(os.path.abspath(__file__))
hat_dir = os.path.dirname(current_directory)
sys.path.append(hat_dir)
from parse.YamlCaseParser import readYaml
from keywords.api_keywords import Keywords
# print(os.getcwd())
# print(current_directory)
file_path = os.path.abspath(os.path.join(current_directory, '../../examples/api-cases-yaml/login.yaml'))
# print(file_path)
class TestRunner2:
data = readYaml(file_path)
# print(data)
@pytest.mark.parametrize('caseinfo',data)#把data的数据拿过来,放到caseinfo里面,一定是一个列表,然后通过parametrize会把列表去掉,变成一个裸字典
def test_case_execute(self,caseinfo):
keyword = Keywords(requests)
# 我不需要所有的数据
# print(caseinfo)
# 输出和测试报告有关的数据
base_info=caseinfo.get(('基础配置'),{})
print("base_info",base_info)
# 输出和测试用例有关的数据
steps = caseinfo.get('用例步骤', None)
# print("steps",steps)
# 这个steps是一个列表,这个列表中嵌套了字典,那么我想拿其中的字典,就要用循环,目前虽然只有一个字典,但是实际工作中可能会有很多不用的接口,一个接口对应一个字典
for step in steps:
print("拿到用例步骤数据",step)
# 开始取到的是字典的键对象,是dict_key[],需要转化成列表
step_name = list(step.keys())[0]
# 开始取到的是字典的值对象,是dict_values[],需要转化成列表
step_value = list(step.values())[0]
key =step_value['操作类型']
try:
# 在KeyWords中找发送请求POST
keyfunc = keyword.__getattribute__(key)
except Exception as e:
print("操作类型不存在",e)
raise
# keyfunc就是发送请求POST() 调用函数,直接把参数传入函数就可以
keyfunc(**step_value)