# api_pytest_yaml **Repository Path**: huntergutt/api_pytest_yaml ## Basic Information - **Project Name**: api_pytest_yaml - **Description**: 基于【pytest+yaml+allure+钉钉通知】设计的api自动化测试框架,支持单接口和业务流程接口测试,用例直接在 yaml 文件中维护,无需编写业务代码,支持生成 allure 报告,并发送到钉钉通知。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2024-10-15 - **Last Updated**: 2025-08-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # api_pytest_yaml ## 1 介绍 api_pytest_yaml是一个基于pytest+yaml+allure+钉钉通知实现的接口自动化测试框架,本框架支持多业务接口依赖、接口加密、单条测试用例 sql 数据库前置/后置、 sql 数据库断言和接口响应断言等,用例直接在 yaml 文件中维护,无需编写业务代码,支持生成 allure 报告,并发送到钉钉通知。 ## 2 实现功能 1. 测试数据隔离:只需要编写 yaml 测试用例文件即可,无需编写业务代码 2. 支持配置全局变量 3. 支持多接口数据依赖:如 A 接口需要同时依赖 B、C 接口的响应数据作为参数 4. 支持单条测试用例sql前置、后置 5. 支持接口加密、文件上传与下载接口测试 6. 支持 2 个或者以上的mysql数据库同时使用 7. 支持数据库断言,直接在测试用例中写入查询的sql语句即可断言,无需编写代码 8. 支持动态多断言,支持同时校验响应数据和sql校验,支持多场景断言 9. 支持统计单个接口运行时长以及执行所有用例执行时长 10. 支持钉钉通知,执行成功后,可选择发送钉钉通知 11. 支持日志模块,打印每个接口的日志信息,可设置 log日志输出级别,决定需要打印的日志 12. 支持生成 allure 报告,从yaml用例中动态获取 feature、story、title、severity等 ## 3 框架结构 ![image-20241013160451087](image/image-20241013160451087.png) - base:存放基础类,封装请求 - config:全局配置文件,数据库地址、文件地址等 - data:存放接口测试数据,包括测试用例、测试数据文件等 - logs:存放测试日志文件 - report:生成 allure 测试报告路径 - testcase:存放测试用例文件目录 - utils:工具类封装,包括断言、日志、数据库操作、钉钉通知、文件操作(yaml 文件读写,删除)、发送 request 请求,加密等 - venv:框架使用的虚拟环境 - conftest 文件:测试夹具,钩子函数生成测试报告 - extract.yaml:接口提取参数存放位置 - environment.xml:allure 报告首页环境显示内容配置 - pytest.ini:pytest 框架全局规范约定 - run.py:pytest 框架统一用例执行入口 ## 4 安装教程 拉取代码后,添加虚拟环境,执行:pip install -r requirements.txt ## 5 框架使用 ### 5.1 编写测试用例 用户编写case时只需要写一个地方: data/yaml/ 文件下 ![image-20241013161339307](image/image-20241013161339307.png) - Business interface :业务接口case所需数据 - Single interface :单接口case所需数据 - download:下载文件接口测试测试放置的路径 - file:上传文件接口测试数据 ### 5.2 登录信息维护 大部分接口请求都需要带 token 或 cookies 信息,可单独写在 user.yaml 文件中维护,本框架作为示例暂时写在 conftest.py 文件中。 框架示例:登录过程包含调用获取加密 key 值接口,将接口请求返回信息写入到 extract.yaml 文件中,从extract.yaml 文件中获取 key 值 对登录密码进行加密,最后将 cookie 写入到 extract.yam 供后续接口使用。 ### 5.3 全局配置文件维护 - **config/config.ini** - 测试 host 地址 - 数据库配置信息 - **config/setting.py** - 文件路径: log 输出路径、提取文件路径、下载文件路径、单接口、业务接口测试数据文件目录等 - 单接口、业务接口 epic 【allure 报告使用】 - log 日志输出级别 - 接口超时时间 - 钉钉机器人配置、是否开启发送钉钉消息 ### 5.4 allure 报告 ![image-20241013155739088](image/image-20241013155739088.png) ## 6 编写 yaml 测试用例 注意:yaml 文件,是通过缩进表示层级关系的,在编写 yaml 测试用例文件时需要注意 ### 6.1 yaml 测试用例结构 生成 allure 报告中的 feature、story(api_name)、title、severity(rank) 数据从测试用例文件中动态获取,epic从config/setting.py 文件中获取。 yaml用例结构有2种方式:单接口和多接口 **单接口**:一个接口对应多条 case,格式为: ```yaml - baseInfo: testCase: - case_name: case1 - case_name: case2 ``` **多接口**:一个接口对应一条 case,要按照执行顺序写用例,格式为: ```yaml - baseInfo: testCase: - case_name: case1 - baseInfo: testCase: - case_name: case2 - baseInfo: testCase: - case_name: case3 ``` 用例使用说明: ```yaml - baseInfo: feature: # 模块名称,缺少字段或空值默认“未定义模块” api_name: # 接口名称,缺少字段或空值默认“未定义接口名称” url: # 必填,请求url,不需要写ip 和 端口 method: POST # 必填 请求方法 GET POST 等 headers: # 选填 cookies: # 选填 testCase: - case_name: case1 # 用例名称,缺少字段或空值默认“未定义用例名称” rank: P1 # 选填 默认P3,P1-P5生效,对应严重等级 blocker、critical、normal、minor、trivial setup: # 选填 用例前置,若需要,下面的 type 和 sqls为必填 database: # 选填 数据库名,配置中可设置默认 type: # 必填 前置方式,db 通过操作数据库前置操作 sqls: # 必填 多条sql语句,必须以;和换行 结尾 INSERT INTO ***; INSERT INTO ***; params: # 选填 请求参数 data: # 选填 请求参数 json: # 选填 请求参数 id: ${get_extract_data(userId)} # 可使用get_extract_data从extract.yaml提取参数 name: test files: # 选填 文件上传 file: ./data/file/test.png # 上传文件路径 download_type: .zip # 选填 测试下载接口,需要保存的文件后缀名 validation: # 断言 - eq: { 'code': 1 } # eq 相等断言 - contains: { 'status_code': 200 } # contains 包含断言 - ne: # 不想等断言 - rv: # 任意值断言 - rt: # 响应时间断言 - db: # 数据库断言 database: uams # 字段选填,数据库名,配置中可设置默认 写了字段不能为空值 sql: SELECT * FROM sys_users WHERE `USERNAME` = 'tzbzyB' # 必填,只执行一条语句 rows: 1 # 选填 返回结果行数,不写字段默认为1 写了字段不能为空值 extract: # 根据接口响应结果进行数据提取,提取到 extract.yaml id: $..id extract_list: # 根据接口响应结果进行数据提取,提取到 extract.yaml 返回列表 teardown: # 选填 用例后置,若需要,下面的 type 和 sqls为必填 database: # 选填 数据库名,配置中可设置默认 type: # 必填 前置方式,db 通过操作数据库前置操作 sqls: # 必填 多条sql语句必须以;和换行 结尾 DELETE FROM ***; DELETE FROM ***; ``` ### 6.2 yaml 测试用例使用解析 #### 6.2.1 case 中依赖数据处理 支持正则表达式/JsonPath提取,根据接口响应结果进行数据提取,提取到 extract.yaml ```yaml extract: # 根据接口响应结果进行数据提取,提取到 extract.yaml userId: $..id ``` extract.yaml文件中存储的数据,可以看到保存的 userId 数据 ```yaml key: 09B5A67A0E3B30CD215A8256976A6F41 Cookie: FULONGTECH_SESSION: 4dd1129f-27e1-42f2-9147-9e4cca1ed2f8 returnUrl: http%3A%2F%2F127.0.0.1%3A8090%2FSmartP%26ID JSESSIONID: 061BF2CB5CC8EC28685E1BC76C3DF77B userId: a9b65b63384942c2962e8c4c9ce76e65 ``` 使用热加载的方式(封装在utils/debugtalk.py工具类)从 extract.yaml 文件中读取 ```yaml id: ${get_extract_data(userId)} ``` #### 6.2.2 case中断言处理 断言支持sql语句断言与响应数据断言 代码如下: ```yaml - baseInfo: testCase: - case_name: validation: # 断言 - eq: { 'code': 1 } # eq 相等断言 - contains: { 'status_code': 200 } # contains 包含断言 - ne: # 不想等断言 - rv: # 任意值断言 - rt: # 响应时间断言 - db: # 数据库断言 database: uams # 字段选填,数据库名,配置中可设置默认 写了字段不能为空值 sql: SELECT * FROM sys_users WHERE `USERNAME` = 'tzbzyB' # 必填,只执行一条语句 rows: 1 # 选填 返回结果行数,不写字段默认为1 写了字段不能为空值 ``` 1、支持多个断言,sql断言与响应断言可以同时使用,当所有断言都成功时表示断言成功,其中一个失败都表示断言失败 2、断言的逻辑是,用期望值与实际值作比较 3、响应断言只需要标注断言类型与期望值即可 如接口请求的整个返回值为: ```json { "code": 1, "msg": "success4Ok", "data": null } ``` 想要对比实际值 msg,写法如下: ```yaml - eq: { 'msg': 'success4Ok' } # 使用相等断言 ``` 4、sql断言需要标注断言类型(db),database、sql、rows 如验证新增用户接口在数据库中是否写入正确:新增用户名为 “tzbzyB”,新增成功后会在uams数据库sys_users表中插入一条数据,执行sql语句 【SELECT * FROM sys_users WHERE `USERNAME` = 'tzbzyB'】若存在查询结果会返回1行数据,则rows设置为1即可。 ```yaml - db: database: uams sql: SELECT * FROM sys_users WHERE `USERNAME` = 'tzbzyB' rows: 1 ``` 若需要验证多个表中都产生新数据写法如下: ```yaml - db: database: uams sql: SELECT * FROM sys_users WHERE `USERNAME` = 'tzbzyB' rows: 1 - db: database: uams sql: SELECT * FROM users WHERE `USERNAME` = 'tzbzyB' rows: 1 ``` #### 6.2.3 case中实现用例setup与teardown 框架中支持sql实现setup与teardown,通过接口请求方式后续实现。框架中支持在项目开始时执行前置,在项目结束后后置,可根据需要自行扩展。 支持每条用例sql前置与后置,方便用例维护。比如添加接口在测试完成后,需要进行用例后置操作删除添加产生的脏数据。 **使用方式:** - 数据库名从 config/config.ini 文件中获取,配置了数据库名后,在sql语句中不需要写数据库名字 - 本框架演示了配置了2个数据库实现方式,其中一个用的比较多的,可以设置成默认方式,本框架中目前只是配置在了utils/mysql_tool/connect_mysql.py,可根据需要设置成全局变量,若只需要一个数据库,则根据需要进行取舍删除不必要的数据。 代码如下: ```yaml - baseInfo: testCase: - case_name: setup: # 选填 用例前置,若需要,下面的 type 和 sqls为必填 database: # 选填 数据库名,配置中可设置默认 type: db # 必填 前置方式,db 通过操作数据库前置操作,不填写不进行前置操作 sqls: # 必填 多条sql语句,必须以;和换行 结尾 INSERT INTO ***; INSERT INTO ***; teardown: # 选填 用例后置,若需要,下面的 type 和 sqls为必填 database: # 选填 数据库名,配置中可设置默认 type: db # 必填 前置方式,db 通过操作数据库前置操作,不填写不进行后置操作 sqls: # 必填 多条sql语句必须以;和换行 结尾 DELETE FROM ***; DELETE FROM ***; ``` allure报告中查看 setup信息、log信息 ![image-20241013213257057](image/image-20241013213257057.png) ![image-20241013213342815](image/image-20241013213342815.png) #### 6.2.4 动态设置allure报告信息 暂时设置了epic、 feature、story(api_name)、title(case_name)、severity(rank)几种,其他的可根据需求进行扩展添加。 ![image-20241013211251712](image/image-20241013211251712.png) ##### 1、epic (1)config/setting.py 文件中设置epic ```python # 单接口 epic single_epic = 'xxx 系统 单接口测试' # 业务接口 epic business_epic = 'xxx 系统 业务接口测试' ``` (2)testcase中使用: testcase/test_business_cases/test_business_cases.py ```python @allure.epic(business_epic) ``` testcase/test_single_cases/test_single_cases.py ```python @allure.epic(single_epic) ``` ##### 2、模块名称 feature ```yaml - baseInfo: feature: # 模块名称,缺少字段或空值默认“未定义模块” ``` ##### 3、故事名称 story 对应yaml文件中 api_name ```YAML - baseInfo: api_name: # 接口名称,缺少字段或空值默认“未定义接口名称” ``` ##### 4、用例标题 title 对应yaml文件中 case_name ```yaml - baseInfo: testCase: - case_name: # 用例名称,缺少字段或空值默认“未定义用例名称” ``` ##### 5、用例等级 severity 对应yaml文件中 rank - P1-P5生效,对应allure报告中严重等级 blocker、critical、normal、minor、trivial - 不填或者除了P1-P5都默认为P3 ```yaml - baseInfo: testCase: - case_name: rank: P1 ``` allure 报告中展示: ![image-20241013203228453](image/image-20241013203228453.png) ## 7 钉钉通知 在 config/setting.py 文件中设置是否开启钉钉通知, 需要设置钉钉群机器人secret与webhook ```python # 钉钉机器人 secret = "SECeb733915c5527442a852e09abc546aa76612a8a78b023bd6596cf62e7ca88445" webhook = "https://oapi.dingtalk.com/robot/send?access_token=72badf9a799f3bccda0cd94ecce0bc2ee85daa3544a1ad03062629aadb5f3a41" # 是否发送钉钉消息 dd_msg = True ``` 推送模板在conftest.py 文件中设置,本框架中推送结果示例如下: ![image-20241013222204666](image/image-20241013222204666.png) ## 8 用例执行范围 在pytest.ini 文件中进行设置,本框架中默认设置为testcase下的所有用例,可根据需要指定单接口,流程接口用例等,若有其他需求可自行需改框架,若需要指定执行P1、P2级用例,可从获取用例后进行用例筛选,获取用例封装在utils/read_files_tools/testcase_yaml.py中。 ## 附:case功能使用演示 只需要在data/yaml用例中维护,不需要在testcase维护 #### 1、**单接口测试用例示例** 一个接口对应多条 case,以下是使用示例: ```yaml - baseInfo: feature: 用户管理 api_name: 删除用户 url: /pidcad/user/delUser method: DELETE headers: Content-Type: application/json;charset=UTF-8 testCase: - case_name: 正常删除用户 rank: P1 setup: type: db database: uams sqls: INSERT INTO `sys_users` (`ID`, `PASSWORD`, `USERNAME`, `NAME`, `CHANGE_PWD_TIME`, `CREATE_BY`) VALUES ('3c6c6c15266548d79f06c996ee1809c4', '8ffedeba55e4300b4fff38817912dbcd', 'gtt', 'gtt', '2024-07-02 01:46:51', 'BEFE2FF1A20F4C419C8A94B7213C5219'); params: userId: 3c6c6c15266548d79f06c996ee1809c4 validation: - eq: { 'code': 1 } - eq: { 'msg': 'success4Ok' } - db: database: uams sql: SELECT * FROM sys_users WHERE `ID` = '3c6c6c15266548d79f06c996ee1809c4' rows: 0 - case_name: 无效删除·缺少必填参数 userId rank: P2 params: validation: - eq: { 'code': 500 } - eq: { 'msg': '服务器报错,请联系管理员!' } ``` #### 2 **流程接口测试用例示例** 要按照执行顺序写用例,以下是使用示例 ```yaml - baseInfo: feature: 用户管理流程 api_name: 添加用户 url: /pidcad/user/addUser method: POST headers: Content-Type: application/json;charset=UTF-8 testCase: - case_name: 正常新增用户 rank: P1 json: email: id: idCard: mobilePhone: name: business phone: roleId: 2 roleName: 数据管理员A username: business validation: - eq: { 'code': 1 } - eq: { 'msg': 'success4Ok' } - db: database: uams sql: SELECT * FROM sys_users WHERE `USERNAME` = 'business' rows: 1 extract: userId: $..id - baseInfo: feature: 用户管理流程 api_name: 删除用户 url: /pidcad/user/delUser method: DELETE headers: Content-Type: application/json;charset=UTF-8 testCase: - case_name: 正常删除用户 rank: P2 params: userId: ${get_extract_data(userId)} validation: - eq: { 'code': 1 } - eq: { 'msg': 'success4Ok' } - db: database: uams sql: SELECT * FROM sys_users WHERE `NAME` = 'business_update' rows: 0 ``` ### #### 加作者微信(记得备注:api_pytest_yaml) ![image-20241013222927827](image/image-20241013222927827.png)