承接前面 Pytest 框架全系列知识点(用例规则、前后置、断言、参数化、Fixture),本篇讲解YAML,是自动化项目实现「代码与用例数据分离」最主流配置文件,接口自动化 90% 项目都会用 yml 存储接口地址、请求参数、测试用例数据,搭配 Pytest+Fixture + 参数化实现标准自动化项目架构。
一、YAML 基础概念 & 优势
1. 什么是 YAML
YAML 全称:YAML Ain't Markup Language(YAML 不是标记语言),是面向人类可读的数据序列化格式 ,后缀.yml/.yaml,自动化领域统一简写.yml,用来替代 JSON/XML 做配置、用例数据存储。
2. YAML 对比 JSON/XML 核心优势
- 极简无冗余符号 :去掉 JSON 的
{}、""、逗号,靠缩进区分层级,编写效率更高; - 天然适配配置场景 :注释友好(
#单行注释),JSON 不支持注释,配置文件可读性碾压 JSON; - 缩进逻辑和 Python 一致,Python 开发上手零门槛;
- 原生支持列表、字典、布尔、数字、嵌套结构,完美匹配接口 JSON 返回格式。
3. YAML 硬性语法规范(避坑必看)
- 严格区分大小写 :
Name和name是两个不同 key; - 禁止使用 Tab 制表符 :只能用空格缩进(一般 2 空格),编辑器 Tab 自动转空格;
- 缩进决定层级关系:同层级缩进空格数必须一致;
#代表单行注释,不能行内注释。
在线工具:JSON 一键转 YAML:https://www.jashtool.com/json/to-yaml(复杂结构快速转换)
二、YAML 全数据类型语法详解(对标 JSON,附对照代码)
yml 支持字符串、数字、布尔、列表、字典、嵌套组合6 种核心数据,下面每种格式附带 yml 写法 + 等效 JSON,适配接口参数场景。
1. 基础键值对(对标 JSON 对象键值)
yaml
python
# yml写法
username: admin
password: 123456
等效 JSON:
python
{"username":"admin","password":"123456"}
2. 数值类型(int 整数 /float 浮点数)
yaml
python
int_num: 99
float_num: 123.456
json
python
{"int_num":99,"float_num":123.456}
3. 布尔值(true/false,小写,自动识别 bool 类型)
yaml
python
is_login: true
is_delete: false
json
python
{"is_login":true,"is_delete":false}
4. 字符串(默认不用引号,特殊字符才加双引号)
yaml
python
# 普通字符串无需引号
title: 用户登录接口
# 含特殊符号用双引号
desc: "接口地址:/api/login,请求方式POST"
json
python
{"title":"用户登录接口","desc":"接口地址:/api/login,请求方式POST"}
5. 列表(短横线- + 空格开头,一行一个元素)
yaml
python
# 接口参数列表
params_list:
- admin
- root
- test01
json
python
{"params_list":["admin","root","test01"]}
6. 嵌套字典(缩进实现子键,接口返回嵌套 json 最常用)
yaml
python
user_info:
uid: 1001
name: 张三
phone: 13800138000
json
python
{"user_info":{"uid":1001,"name":"张三","phone":"13800138000"}}
7. 列表 + 字典混合嵌套(接口用例标准格式!自动化高频)
最常用:一条用例 = 字典,多条用例放入列表
yaml
python
# 登录接口多组测试用例
login_case:
- case_name: 正确账号密码登录
req_data:
username: admin
password: 123456
expect_code: 200
- case_name: 密码错误登录
req_data:
username: admin
password: 654321
expect_code: 401
上面是接口自动化 yml 用例标准模板,后续结合 pytest 参数化直接读取批量执行。
三、PyYAML 环境安装
Python 使用PyYAML库读写 yml 文件,固定版本6.0.1避免版本 API 差异:
python
# 安装指定版本
pip install PyYAML==6.0.1
四、PyYAML 核心:yml 读取 & 写入代码封装
封装通用工具类:read_yaml读取、write_yaml新增写入、clear_yaml清空文件,自动化项目通用工具函数。
python
import yaml
# 1. 读取yml指定key数据
def read_yaml(file_path, key=None):
"""
:param file_path: yml文件路径
:param key: 需要读取的键,不传则返回全部数据
"""
with open(file_path, encoding="utf-8", mode="r") as f:
data = yaml.safe_load(f) # safe_load安全加载,规避恶意代码注入
if key:
return data.get(key)
return data
# 2. 追加/写入yml文件(a+追加,w覆盖)
def write_yaml(file_path, data):
with open(file_path, encoding="utf-8", mode="a+") as f:
yaml.safe_dump(data, stream=f, allow_unicode=True)
# allow_unicode=True:中文不乱码,必加参数!
# 3. 清空yml文件内容
def clear_yaml(file_path):
with open(file_path, encoding="utf-8", mode="w") as f:
f.truncate()
# 测试用例
def test_yml_opt():
# 写入数据
test_data = {"str": "12345"}
write_yaml("test.yml", test_data)
# 读取数据
res = read_yaml("test.yml", "str")
print("读取结果:", res)
# clear_yaml("test.yml") # 按需清空
关键参数
allow_unicode=True:不加会出现中文转 unicode 编码(\u5f20\u4e09),存储中文 yml 必带。
五、实战 1:Pytest+YAML 实现接口用例数据分离(项目落地)
步骤 1:新建api_case.yml,存储登录接口多组用例
XML
login_api:
- case_title: 正常登录
url: https://jsonplaceholder.typicode.com/users/1
method: GET
expect_uid: 1
- case_title: 异常ID查询
url: https://jsonplaceholder.typicode.com/users/999
method: GET
expect_uid: None
步骤 2:pytest 参数化读取 yml,自动批量执行用例
python
import pytest
import requests
from common.yaml_util import read_yaml # 导入上面封装的读取函数
# 读取yml内登录用例
case_data = read_yaml("api_case.yml", "login_api")
# 参数化批量生成用例
@pytest.mark.parametrize("case", case_data)
def test_login_api(case):
# 从yml取出接口参数
url = case["url"]
expect = case["expect_uid"]
res = requests.get(url)
# 结合之前assert断言
if res.status_code ==200:
actual_uid = res.json()["id"]
assert actual_uid == expect, f"{case['case_title']}校验失败,预期{expect},实际{actual_uid}"
else:
assert expect is None
执行效果:yml 里 2 组用例自动生成 2 条 pytest 用例,新增测试场景只需要修改 yml
不用改动 Python 代码,完美实现数据代码分离。
六、实战 2:Fixture+YAML 全局配置(conftest 读取全局环境配置)
1. 项目根目录config.yml(全局环境配置:域名、请求头)
yaml
python
base_url: https://jsonplaceholder.typicode.com
headers:
Content-Type: application/json
token: test_token_001
2. conftest.py 全局 fixture,全项目任意用例直接引用
python
import pytest
from common.yaml_util import read_yaml
@pytest.fixture(scope="session")
def global_config():
# 项目全局读取配置yml
config = read_yaml("config.yml")
return config
3. 任意测试用例直接调用全局配置
python
def test_post_query(global_config):
base = global_config["base_url"]
header = global_config["headers"]
url = f"{base}/posts/1"
res = requests.get(url,headers=header)
assert res.status_code ==200
七、PyYAML 常用避坑总结
- 中文乱码:safe_dump必须加allow_unicode=True;
- 缩进报错:统一 2 空格缩进,全程禁用 Tab;
- 加载文件空值:yml 空行、格式错误会导致safe_load返回 None;
- 安全规范:优先用yaml.safe_load(),禁止yaml.load()(老版本存在代码注入漏洞);
- 列表横线-后面必须带空格,-admin写法非法,正确- admin。
八、拓展:自动化项目 yml 分层规范(企业项目目录)
自动化项目/
├─ config/
│ └─ env.yml # 全局环境配置(域名、数据库地址)
├─ testcase/
│ ├─ login_case.yml # 登录模块用例
│ └─ user_case.yml # 用户模块用例
├─ common/
│ └─ yaml_tool.py # 封装yml读写工具类
└─ conftest.py # fixture全局读取配置