文章目录
- 一、YAML详解
- 1.YAML作用
- 2.YAML语法结构
- 3.YAML数据类型
- 3.1.对象
- 3.2.数组
- 3.3.标量
- 4.YAML的引用
- 5.YAML类型转换
- 二、YAML的读写与清空
- 1.YAML的读
- 2.YAML的写
- 3.YAML的清空
- 三、pytest的parametrize简单数据驱动
- 四、pytest的parametrize结合yaml实现数据驱动
- 五、解决pytest + allure + yaml实现数据驱动生成测试报告及定制导致的页面丑格式陋问题
- 1.问题描述
- 2.解决方法
一、YAML详解
YAML是一个可读性高,用来表达数据序列化的格式。YAML是 “YAML Ain’t a Markup Language”(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言),但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。
YAML它能够和JSON数据相互转化,它本身也是有很多数据类型可以满足我们接口
的参数类型,扩展名可以是.yml
或.yaml
1.YAML作用
- 全局配置文件:基础路径,数据库信息,账号信息,日志格式,报告名称等。
- 编写测试用例:接口自动化测试用例
2.YAML语法结构
-
1.区分大小写(大小写敏感)
Name: 张三 name: 张三
-
2.可以使用
#
作为注释(YAML仅支持单行注释)# 第一行注释 Name: 张三 # 第一行注释 name: 张三
-
3.使用缩进表示层级关系
- 缩进只能使用
空格
,不能用Tab
制表符 - 缩进的
空格数量
不重要,但是同一层级的元素左侧必须对齐
province: "湖南省" city1: "永州市" city2: "长沙市" area1: "雨花区" area2: "天心区"
Three_stage_linkage: province: city: area: "雨花区"
- 缩进只能使用
-
4.一个文件可以包含多个文件的内容
- 用
---
三个破折号表示一份内容的开始 - 用
...
三个小数点表示一份内容的结束,但并不是必需的
--- # 第一份内容 name: first ... --- # 第二份内容 name: second ...
- 用
-
5.字符串一般默认可以不使用引号,必须时才使用
3.YAML数据类型
对象
:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)数组
:一组按次序排列的值,又称为序列(sequence) / 列表(list)标量(scalars)
:单个的、不可再分的值
3.1.对象
-
对象键值对使用冒号结构表示
key: value
,冒号后面要加一个空格例一(单个)
key: value
例二(多层嵌套)
key: child-key1: value1 child-key2: value2
例三(流式风格语法)
key: { child1: value1, child2: value2 }
-
较为复杂的对象格式,可以使用问号加一个空格代表一个复杂的key,配合一个冒号加一个空格代表一个 value:
? - complexkey1 - complexkey2 : - complexvalue1 - complexvalue2
3.2.数组
-
以
-
开头的行表示构成一个数组:- A - B - C
- - A - B - C
-
YAML支持多维数组,可以使用行内表示:
key: [value1, value2, ...]
-
支持多维数组,用缩进表示层级关系
values: - - value1 - value2 - - value3 - value4
-
复合结构:数组和对象可以构成复合结构,例:
languages: - Java - PHP - Python websites: YAML: yaml.org Python: python.org
3.3.标量
标量:单个的、不可再分的值。属于YAML中最基本的数据类型
- 字符串
- 布尔值
- 整数
- 浮点数
- Null
- 时间
- 日期
#字符串
string:
- 哈哈
- 'Hello world' #可以使用双引号或者单引号包裹特殊字符(当有特殊字符时:双引号不会被转义,其它的都会加一个转义符 \)
- newline
newline2 #字符串可以拆成多行,每一行会被转化成一个空格
#布尔值
boolean:
- TRUE #true,True都可以
- FALSE #false,False都可以
#整数
int:
- 123
- 0b1010_0111_0100_1010_1110 #二进制表示
#浮点数
float:
- 3.14
- 6.8523015e+5 #可以使用科学计数法
#Null
null:
nodeName: 'node'
parent: ~ #使用~表示null(null、Null 和 ~ 都可以表示空,不指定值默认也是空)
#时间
datetime:
- 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
#日期
date:
- 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
- 字符串
-
多行字符:字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格
str: 这是一段 多行 字符串
-
保留换行:使用竖线符
|
来表示该语法,每行的缩进和行尾空白都会被去掉,而额外的缩进会被保留lines: | 我是第一行 我是第二行 我是吴彦祖 我是第四行 我是第五行
-
折叠换行:使用右尖括号
>
来表示该语法,只有空白行才会被识别为换行,原来的换行符都会被转换成空格lines: > 我是第一行 我也是第一行 我仍是第一行 我依旧是第一行 我是第二行 这么巧我也是第二行
-
4.YAML的引用
为了避免重复的定义,YAML 提供了由锚点标签
&
和引用标签*
组成的语法,利用这套语法可以快速引用相同的一些数据。
-
&
锚点和*
别名,可以用来引用:defaults: &defaults adapter: postgres host: localhost development: database: myapp_development <<: *defaults test: database: myapp_test <<: *defaults
相当于:
defaults: adapter: postgres host: localhost development: database: myapp_development adapter: postgres host: localhost test: database: myapp_test adapter: postgres host: localhost
-
&
用来建立锚点(defaults),<<
表示合并到当前数据,*
用来引用锚点
5.YAML类型转换
-
YAML 支持使用严格类型标签:
!!
(双感叹号+目标类型)来强制转换类型a: !!float '666' # !! 为严格类型标签,字符串转为浮点数 b: '666' # 其实双引号也算是类型转换符 c: !!str 666 # 整数转为字符串 d: !!str 666.66 # 浮点数转为字符串 e: !!str true # 布尔值转为字符串 f: !!str yes # 布尔值转为字符串 g: !!int '666' # 字符串转为整数
二、YAML的读写与清空
-
安装第三方插件:
pip install pyyaml
pip install pyyaml
1.YAML的读
-
方法一:
import yaml def read_yaml(yaml_path): with open(yaml_path, encoding="utf-8") as f: result = yaml.safe_load(f) return result result = read_yaml("D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml") print(result)
-
方法二:
import yaml def read_yaml(yaml_path): with open(yaml_path, encoding="utf-8") as f: result = yaml.load(f, Loader=yaml.FullLoader) return result result = read_yaml("D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml") print(result)
2.YAML的写
-
方法一:(覆盖写入)
import yaml def write_yaml(yaml_path, data): with open(yaml_path, mode="w", encoding="utf-8") as f: result = yaml.dump(data, stream=f, allow_unicode=True) path = "D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml" data = {'province': {'city1': '长沙市', 'city2': '永州市'}} write_yaml(path, data)
-
方法二:(覆盖写入)
import yaml def write_yaml(yaml_path, data): with open(yaml_path, mode="w", encoding="utf-8") as f: result = yaml.safe_dump(data, stream=f, allow_unicode=True) path = "D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml" data = {'province': {'city1': '长沙市', 'city2': '永州市'}} write_yaml(path, data)
-
方法三:(追加写入)
import yaml def add_to_yaml(yaml_path, data): with open(yaml_path, mode="a+", encoding="utf-8") as f: result = yaml.safe_dump(data, stream=f, allow_unicode=True) path = "D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml" data = {'province': {'city1': '长沙市', 'city2': '永州市'}} add_to_yaml(path, data)
3.YAML的清空
-
方法一:
# 清空yaml文件内容 def clean_yam(yaml_path): with open(yaml_path, mode="w", encoding="utf-8") as f: f.truncate() path = "D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml" clean_yam(path)
-
方法二:
def clean_yam(yaml_path): with open(yaml_path, mode="w", encoding="utf-8") as f: pass path = "D:\\develop\\PyCharm\\workspace\\api_frame\\testcase\\test_first_yaml.yaml" clean_yam(path)
三、pytest的parametrize简单数据驱动
-
使用
@pytest.mark.parametrize("参数名", 参数值(可以是list或tuple))
实现数据驱动 -
数据驱动
import pytest class TestFirstClass(): @pytest.mark.parametrize("name,age", [["张三", 18], ["李四", 28], ["王五", 20]]) def test_query(self, name, age): print(name, age)
四、pytest的parametrize结合yaml实现数据驱动
-
使用
@pytest.mark.parametrize("参数名", 参数值(可以是list或tuple))
实现数据驱动 -
1.
test_first_yaml.yaml文件内容
- feature: 模块名1 story: 接口名1 title: 用例标题1 request: method: 请求方式 url: 请求路径 headers: 请求头 data: 请求数据(可以是data,json,file等) validate: 断言 - feature: 模块名2 story: 接口名2 title: 用例标题2 request: method: 请求方式 url: 请求路径 headers: 请求头 data: 请求数据(可以是data,json,file等) validate: 断言
-
2.
yaml_util.py文件内容
import yaml class YamlUtil(): def __init__(self, yaml_path): self.yaml_path = yaml_path def read_yaml(self): with open(self.yaml_path, encoding="utf-8") as f: result = yaml.safe_load(f) return result
-
3.
test_second_file.py
文件内容import pytest from commons.yaml_util import YamlUtil class TestFirstClass(): @pytest.mark.parametrize("caseinfo", YamlUtil("./testcase/test_first_yaml.yaml").read_yaml()) def test_query(self, caseinfo): print(caseinfo)
-
4.结果
注意:
如果实现数据驱动使用allure测试报告定制会导致allure测试报告页面格式丑陋
五、解决pytest + allure + yaml实现数据驱动生成测试报告及定制导致的页面丑格式陋问题
1.问题描述
2.解决方法
-
找到项目下 venv/Lib/site-packages/allure_pytest/listener.py 源码文件,删除如图所示内容保存,重新启动项目查看allure测试报告结果