Interface
前言
简单讲述框架的使用
本框架主要基于:Python+Pytest+Yaml(Yaml+CSV)+Redis+Allure+Log+Mysql 实现接口自动化框架
Git地址:https://gitee.com/make_a_summer/interface.git
项目作者:唐松(挽一夏)
个人邮箱:tasng@foxmail.com (欢迎探讨学习进步)
实现功能
- 测试数据隔离,实现数据驱动。使用yaml文件,或者yaml-csv文件实现单接口多组数据
- 接口关联使用Redis存储数据
- 支持多接口数据依赖:如A接口需要同时依赖B、C接口的响应数据作为参数。提取接口单个值,提取接口返回列表
- 数据库断言:直接在测试用例中写入查询的sql即可断言,无需编写代码
- 动态多断言: 如接口需要同时校验响应数据和sql校验,支持多场景断言
- 日志模块: 打印每个接口的日志信息
- 支持mock接口
- 统计接口的运行时长
- 自定义拓展字段: 如用例中需要生成的随机数据,可直接调用
运行接口框架前准备
1. 安装Python
2. 安装依赖库,pip install -r requirements.txt
3. 配置config.yaml文件,配置测试环境,redis,数据库信息等。
redis安装,配置账号密码。我是默认安装,没有配置账号密码
切换环境:
-
config.yaml文件中,增加环境变量,格式固定按照写就好了。记得把变量都写死
-
config.py文件,修改环境变量
Ps: 想再不同环境中,都能执行代码,前提是一些变动字段,都写到config.yaml维护,不同环境中维护一套字段。
目录架构
|-common // 辅助类,用于整个测试框架
| └── debugtalk.py // 自定义函数供测试脚本调用。生成随机数、日期时间戳等常用的功能
|-config // 配置
| └── config.py // 读取项目配置文件:config.yaml
| └── config.yaml // 项目配置文件
| └── redis_config.py // redis读取/写入方法
| └── setting.py // 项目基础路径
|-data // CSV测试文件
|-files // 上传文件
|-logs // 日志
|-reports // 测试报告
|-testcase // 测试用例
|-conftest.py // 运行前之前操作,清空redis
|-util_tools // 工具库文件
| └── db_connector // 数据库模块
| └── mysql_util.py // MySQL工具类
| └── handle_data // 测试文件操作模块
| └── csv_analysis_params.py // Yaml文件使用CSV格式,进行数据处理
| └── csv_handler.py // 读取CSV文件
| └── yaml_handler.py // 读取Yaml文件
| └── other_util // 其他工具类
| └── allure_type.py // Allure报告步骤中,数据格式处理
| └── genrate_id.py // 测试用例ID
| └── notify // 通知
| terminal
| └── terminal_reporter.py // 控制台打印样式
| └── wechat_work_notifier.py // 企业微信通知
| └── email_notifier.py // 邮件通知
| └── notify_sender.py // 配置发送通知类型
| └── yaml_process // Yaml文件处理
| └── yaml_analysis.py // Yaml数据规范、替换、发送请求、数据提取、执行断言
| └── yaml_extract.py // 处理数据提取
| └── yaml_replace.py // 处理数据替换
| └── assertion_util.py // 封装断言
| └── mock_util.py // 封装mock
| └── redis_util.py // 封装redis
| └── logger_util.py // 封装日志
| └── requests_util.py // 封装发送请求
|-conftest.py // 收集运行时间等
|-pytest.ini
|-environment.xml // allure报告中环境配置
|-run.py // 运行入口
接口文档
微信公众号-标签管理:
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
| 微信公众号-标签管理 |
|---|
| 登录 |
| 查询标签 |
| 修改标签 |
| 删除标签 |
| 文件上传 |
这位博主的评论区下有接口可以练习,在windows下直接运行就可以用,我之前写了,可以跑通。
现在换了Mac本后不能运行他的接口,懒得在继续搞了,随即放弃。有兴趣的朋友,记得看完他的视频,操作下,非常有必要。
B站博主学习资料,且配套测试接口。
博主视频评论区中,有练习接口
测试用例
创建测试用例
在testcase目录下分别创建两个文件,yaml文件存储测试数据,py文件运行。
比如在testcase目录userManager文件下新建用户查询接口测试
- 创建YAML测试文件,编写接口数据
-
name: 用户查询
base_url: ${get_base_url(base_url)}
request:
headers: ${get_headers(data)}
method: post
path: /dar/user/queryUser
data:
user_id: 123839387391912
extract:
validation:
- code: 200
- contain: { "msg": "查询成功!" }
- 创建执行YAML的Py文件,进行读取YAML文件,发送接口请求
@allure.feature(next(m_id) + '用户管理模块')
class TestUserManager:
@allure.story(next(c_id) + '用户查询')
@allure.description('用户查询接口')
@pytest.mark.parametrize('caseinfo', read_testcase_file('testcase/userManager/queryUser.yaml'))
def test_user_query(self, caseinfo):
allure.dynamic.title(caseinfo['name'])
YamlAnalysis().yaml_analysis_execution(caseinfo)
YAML用例格式规范
YAML测试文件,编写接口数据,其中有严格的关键字层级,编写时需遵守
-
name: # 用例名称
base_url: # 用例基础URL
request:
headers: # 请求头 (可选)
cookies: # cookies (可选)
method: # 请求方式
path: # 接口请求路径
data/json/params: # 请求参数 (可选)
extract: # 提取参数 (可选)
# extract_list: # 提取参数列表
validation: # 断言
必填项:
4个一级关键字:name、base_url、request、validation
2个二级关键字:method、path
选填项:
extract:提取接口返回值中,单个key的值
extract_list:提取接口返回值中,指定key的所有值列表
YAML用例数据编写
一个YAML文件管理,能管理一组或者多组数据。YAML文件中有几组数据,就发送几次请求。
yaml文件中有两组测试数据,所以能执行两次请求
-
name: wx_获取token成功
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/token
data:
grant_type: client_credential
appid: wx2a3d01a57cd117f4
secret: 938fa8f53264eecf325dcd67546c747e
extract:
access_token: $.access_token
validation:
- contain: expires_in
-
name: wx_获取token失败
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/token
data:
grant_type:
appid: wx2a3d01a57cd117f4
secret: 938fa8f53264eecf325dcd67546c747e
extract:
validation:
- contain: errcode

YAML+CSV管理用例
看上方发现,在YAML文件中管理多组测试数据,一组两组还好,多了之后YAML中数据就过多,不好查看与管理。
所有就引入了CSV管理,对可变的参数进行处理
-
1、CSV文件存储在data目录下
-
2、使用CSV方式做参数化,在YAML文件中,要做对应修改,新增关键字
parameters,与对应的读取数据格式$csv{XXX}
下面使用同一个接口,展示CSV管理用例
1、data目录下,新建CSV文件,有四个字段需要被替换使用
name,appid,secret,grant_type,validation
csv-获取token,wx2a3d01a57cd117f4,938fa8f53264eecf325dcd67546c747e,client_credential,access_token
csv-appid必须检查,"",938fa8f53264eecf325dcd67546c747e,client_credential,errcode
csv-appid错误检查,111111111111111,938fa8f53264eecf325dcd67546c747e,client_credential,errcode
csv-secret缺失,wx2a3d01a57cd117f4,"",client_credential,errcode
csv-secret错误检查,wx2a3d01a57cd117f4,22222222222222,client_credential,errcode
csv-grant_type缺失,wx2a3d01a57cd117f4,938fa8f53264eecf325dcd67546c747e,"",errcode
csv-grant_type错误检查,wx2a3d01a57cd117f4,938fa8f53264eecf325dcd67546c747e,1111111111111,errcode
2、YAML测试文件,加入 parameters 字段,并将csv文件路径传入。被替换的字段用$csv{XXX}格式
-
name: $csv{name}
base_url: ${get_base_url(base_wx_url)}
# 使用csv格式,就要加入'parameters'字段。需要替换的数据使用$csv{}进行替换
parameters:
name-appid-secret-grant_type-validation: data/wx_tag_login.csv
request:
method: post
path: /cgi-bin/token
data:
appid: $csv{appid}
secret: $csv{secret}
grant_type: $csv{grant_type}
extract:
access_token: $.access_token
validation:
- contain: $csv{validation}

用例中提取参数
提取参数有两个方式,根据接口实际结果使用。支持使用jsonpath,正则表达式。提取的接口关联参数存储到:redis 文件中
extract :提取单个数据
extract_list : 提取的数据是列表
提取单个数据
不指定参数提取
适用于接口返回值中,只有一组数据。
比如创建接口,返回值需要提取id。使用jsonpath提取参数,并存入Redis中
创建接口返回接口:
{"tag": {"id": 268, "name": "test86483"}}
yaml文件中,使用jsonpath提取tag下的id,存入Redis中
-
name: wx-创建标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/create?access_token=${get_extract_data(access_token)}
json:
tag:
name: test${get_random_number(10000, 99999)}
extract:
tag_id: $.tag.id
validation:
- code: 200
运行成功后,成功写入Redis中

提取指定参数
适用于接口返回中存在多组数据。
比如查询接口中,提取name = case86的id,做接口关联时候,为了保持数据的一致性。就要提取指定数据。
查询接口返回值
{
"tags": [
{
"id": 2,
"name": "星标组",
"count": 0
},
{
"id": 100,
"name": "22214767",
"count": 0
},
{
"id": 129,
"name": "case",
"count": 0
},
{
"id": 130,
"name": "case60",
"count": 0
},
{
"id": 131,
"name": "case86",
"count": 0
},
{
"id": 153,
"name": "哈哈哈63",
"count": 0
},
{
"id": 154,
"name": "哈哈哈45",
"count": 0
},
{
"id": 155,
"name": "哈哈哈54",
"count": 0
}
]
}
yaml文件中,使用jsonpath提取name = case86下的id,存入Redis中
-
name: wx-查询标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/get?access_token
params:
access_token: ${get_extract_data(access_token)}
extract:
caseid: "$.tags[?(@.name=='case86')].id"
validation:
- code: 200
- contain: name
指定提取name = case86下的id,存入Redis中

提取列表
查询标签接口,返回值中所有的id。分别使用正则与jsonpath提取,使用extract_list关键字
接口返回
{
"tags": [
{
"id": 2,
"name": "星标组",
"count": 0
},
{
"id": 100,
"name": "22214767",
"count": 0
},
{
"id": 129,
"name": "case",
"count": 0
},
{
"id": 130,
"name": "case60",
"count": 0
},
{
"id": 131,
"name": "case86",
"count": 0
},
{
"id": 153,
"name": "哈哈哈63",
"count": 0
},
{
"id": 154,
"name": "哈哈哈45",
"count": 0
},
{
"id": 155,
"name": "哈哈哈54",
"count": 0
}
]
}
正则提取,提取列表使用extract_list关键字,提取所有id值
-
name: wx-查询标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/get?access_token
params:
access_token: ${get_extract_data(access_token)}
extract_list:
all_ids: '"id":\s*(\d+)'
validation:
- code: 200
- contain: name
jsonpath提取,提取列表使用extract_list关键字,提取所有goodsId值
-
name: wx-查询标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/get?access_token
params:
access_token: ${get_extract_data(access_token)}
extract_list:
all_ids: "$.tags[*].id"
validation:
- code: 200
- contain: name
运行成功,存入Redis中

参数使用
单个参数使用
这一步就是接口关联的实际用法。上一个接口返回值中提取后存入,下一个接口中读取使用
固定格式写法:${get_extract_data(xxx)}
比如查询标签—编辑标签接口
查询标签,提取name = case86的id,编辑标签中使用该id
-
name: wx-编辑标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/update?access_token= ${get_extract_data(access_token)}
json:
tag:
id: ${get_extract_data(caseid)}
name: test${get_random_number(100000, 999999)}
extract:
validation:
- code: 200
- contain: ok
多个参数使用
上面提取了列表,并存储,那么就到了使用的时候
Redis中,存入多个值,yaml文件中引用。 id: ${get_extract_data(all_ids,1)},根据索引取第一个值。0随机取值,-1取全部值。方法在debugtalk.py文件中,可以自行扩展。
-
name: wx-编辑标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/update?access_token= ${get_extract_data(access_token)}
json:
tag:
id: ${get_extract_data(all_ids,1)}
name: test${get_random_number(100000, 999999)}
extract:
validation:
- code: 200
- contain: ok
用例中接口传参如何实现
1、通过上个接口发送请求,得到token请求值,存储到redis中
2、YAML文件中,通过debugtalk.py文件中,使用read_extract_redis方法,获取redis中数据
读取关联值,因为提取的有单个数据、列表数据,所以提取的方式略有不同
单个参数,如上述token值,在YAML文件中,使用${get_extract_data(token)}
列表参数,如上述goodIds第1个值,在YAML文件中,使用${get_extract_data(goodIds,0)}
redis中,已经存储数据
编写方式,需要替换取extract.yaml文件值的地方,使用$ {get_extract_data(xxx)},列表使用${get_extract_data(xxx,位数)}
# 微信删除标签接口,如需传入token
params:
token: ${get_extract_data(token)}
# 编辑标签中,如想编辑第1个标签,就取第一个id值:2
json:
id: ${get_extract_data(all_ids,1)}
用例中函数扩展使用
在使用的过程中,发现需要扩展一些方法函数,可以在debugtalk.py文中编写实现。比如看例子时候发现,URL、headers、cookies都是 x x ( ) 格式。这就是在 d e b u g t a l k . p y 文件中定义了写函数,并进行替换使用。如 ‘ {xx()} 格式。这就是在debugtalk.py文件中定义了写函数,并进行替换使用。如 ` xx()格式。这就是在debugtalk.py文件中定义了写函数,并进行替换使用。如‘{get_base_url()}、${get_headers()}、 ${get_extract_data(Cookie)}`
这些方法均在debugtalk.py文件中编写,yaml用例中使用。
class DebugTalk:
# 基础url
@classmethod
def get_base_url(cls, node_name):
"""
:param node_name: base_url
:return:
"""
return read_config_file('base', node_name)
# mysql数据库
@classmethod
def get_mysql_config(cls, node_name):
"""
:param node_name: mysql
:param node_name:
:return:
"""
return read_config_file('mysql', node_name)
# headers请求头
@classmethod
def get_headers(cls, params_type):
headers_mapping = {
'data': {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
'json': {'Content-Type': 'application/json;charset=UTF-8 '}
}
header = headers_mapping.get(params_type)
if header is None:
raise ValueError('不支持其他类型的请求头设置')
return header
# 随机数
@classmethod
def get_random_number(cls, min, max):
return random.randint(int(min), int(max))
微信创建标签接口时,就可以使用随机数函数
-
name: wx-创建标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/create?access_token=${get_extract_data(access_token)}
json:
tag:
name: test${get_random_number(10000, 99999)}
extract:
validation:
- code: 200
断言类型
本框架只实现了五种类型断言
状态码断言、包含模式断言、相等断言、不相等断言、数据库断言
validation:
- contain: {'msg': '登录成功'} # 包含模式
- code: 200 # 接口的响应状态码断言
- eq: {'msg': '登录成功'} # 相等断言
- ne: {'msg': '登录失败'} # 不相等断言
- db: SELECT name, fee FROM testcase.`user` WHERE id=4; # 数据库断言
allure报告
执行run.py文件,在reports文件allures文件下,打开index.html文件,即可查看

收到邮箱通知

运行流程详解
✅ 1. 本地开启Redis服务后,启动入口:run.py
if __name__ == '__main__':
pytest.main() # 运行 pytest 收集并执行测试用例
shutil.copy('environment.xml', './reports/temps') # 复制环境信息
os.system("allure generate reports/temps -o reports/allures --clean") # 生成 Allure 报告
✅ 2. pytest 收集用例(根据 pytest.ini 配置)
- 测试路径:
testcase/ - 文件命名:
test_*.py - 类命名:
Test* - 函数命名:
test_* - 并发执行:
-n auto(pytest-xdist)—暂时去掉 - 报告缓存:
--alluredir=reports/temps
✅ 3. 测试用例结构(YAML 驱动)
每个测试用例是一个 YAML 文件,结构如下:
-
name: wx-编辑标签
base_url: ${get_base_url(base_wx_url)}
request:
method: post
path: /cgi-bin/tags/update?access_token= ${get_extract_data(access_token)}
json:
tag:
id: ${get_extract_data(caseid)}
name: test${get_random_number(100000, 999999)}
extract:
validation:
- code: 200
- contain: ok
✅ 4. 用例解析与执行流程:YamlAnalysis.yaml_analysis_execution()
| 步骤 | 说明 |
|---|---|
| ① 读取 YAML 文件 | yaml_handler.py → read_testcase_file() |
| ② 参数化替换 | csv_analysis_params.py → CSV 数据替换 $csv{key} |
| ③ 变量替换 | yaml_replace.py → 替换 ${get_extract_data(key)} 等 |
| ④ Mock 判断 | mock_util.py → 如果存在 mock: 字段,则替换真实请求 |
| ⑤ 发送请求 | requests_util.py → execute_request() |
| ⑥ 提取响应值 | yaml_extract.py → extract_data() / extract_data_list() |
| ⑦ 断言验证 | assertion_util.py → assert_result() |
| ⑧ Allure 报告 | allure.attach() 记录请求、响应、断言、提取数据 |
✅ 5. 断言支持类型
| 断言类型 | 示例 |
|---|---|
| 状态码断言 | code: 200 |
| 包含断言 | contain: success |
| 相等断言 | eq: {success: true} |
| 不相等断言 | ne: {code: 500} |
| 数据库断言 | db: SELECT COUNT(*) FROM order WHERE id=123 |
✅ 6. 数据传递机制
- 保存接口提取的值到Redis(如订单号、token)
- DebugTalk.get_extract_data():在 YAML 中通过
${}动态读取 - write_extract_redis():提取后写入
Redis
✅ 7. 日志与异常处理
- 日志记录:
logger_util.py→ 控制台 + 日志文件(按天轮转) - 异常捕获:每个模块都 try-catch 并记录日志,确保失败用例不中断整个流程
✅ 8. 报告与通知
- Allure 报告:自动生成到
reports/allures/index.html - 邮件通知:
conftest.py→pytest_terminal_summary()钩子函数收集结果并发送邮件


1320

被折叠的 条评论
为什么被折叠?



