自动化测试基础——Pytest框架之YAML详解以及Parametrize数据驱动

文章目录

一、YAML详解

YAML是一个可读性高,用来表达数据序列化的格式。YAML是 "YAML Ain't a Markup Language"(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言),但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。
YAML它能够和JSON数据相互转化,它本身也是有很多数据类型可以满足我们接口
的参数类型,扩展名可以是 .yml.yaml

1.YAML作用

  1. 全局配置文件:基础路径,数据库信息,账号信息,日志格式,报告名称等。
  2. 编写测试用例:接口自动化测试用例

2.YAML语法结构

  • 1.区分大小写(大小写敏感)

    yaml 复制代码
    Name: 张三
    name: 张三
  • 2.可以使用 # 作为注释(YAML仅支持单行注释)

    yaml 复制代码
    # 第一行注释
    Name: 张三
    # 第一行注释
    name: 张三
  • 3.使用缩进表示层级关系

    • 缩进只能使用 空格,不能用 Tab 制表符
    • 缩进的 空格数量 不重要,但是 同一层级的元素左侧必须对齐
    yaml 复制代码
    province: "湖南省"
      city1: "永州市"
      city2: "长沙市"
        area1: "雨花区"
        area2: "天心区"
    yaml 复制代码
    Three_stage_linkage:
     province:
      city:
       area: "雨花区"
  • 4.一个文件可以包含多个文件的内容

    • --- 三个破折号表示一份内容的开始
    • ... 三个小数点表示一份内容的结束,但并不是必需的
    yaml 复制代码
    ---
    # 第一份内容
    name: first
    ...
    
    ---
    # 第二份内容
    name: second
    ...
  • 5.字符串一般默认可以不使用引号,必须时才使用

3.YAML数据类型

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  • 标量(scalars):单个的、不可再分的值

3.1.对象

  • 对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格

    例一(单个)

    yaml 复制代码
    key: value

    例二(多层嵌套)

    yaml 复制代码
    key:
      child-key1: value1
      child-key2: value2

    例三(流式风格语法)

    yaml 复制代码
    key: { child1: value1, child2: value2 }
  • 较为复杂的对象格式,可以使用问号加一个空格代表一个复杂的key,配合一个冒号加一个空格代表一个 value:

    yaml 复制代码
    ?
      - complexkey1
      - complexkey2
    :
      - complexvalue1
      - complexvalue2

3.2.数组

  • - 开头的行表示构成一个数组:

    yaml 复制代码
    - A
    - B
    - C
    yaml 复制代码
    -
     - A
     - B
     - C
  • YAML支持多维数组,可以使用行内表示:

    yaml 复制代码
    key: [value1, value2, ...]
  • 支持多维数组,用缩进表示层级关系

    yaml 复制代码
    values:
      -
        - value1
        - value2
      -
        - value3
        - value4
  • 复合结构:数组和对象可以构成复合结构,例:

    yaml 复制代码
    languages:
      - Java
      - PHP
      - Python
    websites:
      YAML: yaml.org
      Python: python.org

3.3.标量

标量:单个的、不可再分的值。属于YAML中最基本的数据类型

  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期
yaml 复制代码
#字符串
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
  • 字符串
    • 多行字符:字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格

      yaml 复制代码
      str: 这是一段
        多行
        字符串
    • 保留换行:使用竖线符 | 来表示该语法,每行的缩进和行尾空白都会被去掉,而额外的缩进会被保留

      yaml 复制代码
      lines: |
        我是第一行
        我是第二行
          我是吴彦祖
            我是第四行
        我是第五行
    • 折叠换行:使用右尖括号 > 来表示该语法,只有空白行才会被识别为换行,原来的换行符都会被转换成空格

      yaml 复制代码
      lines: >
        我是第一行
        我也是第一行
        我仍是第一行
        我依旧是第一行
      
        我是第二行
        这么巧我也是第二行

4.YAML的引用

为了避免重复的定义,YAML 提供了由锚点标签 & 和引用标签 * 组成的语法,利用这套语法可以快速引用相同的一些数据。

  • & 锚点和 * 别名,可以用来引用:

    yaml 复制代码
    defaults: &defaults
      adapter:  postgres
      host:     localhost
    
    development:
      database: myapp_development
      <<: *defaults
    
    test:
      database: myapp_test
      <<: *defaults

    相当于:

    yaml 复制代码
    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 支持使用严格类型标签:!!(双感叹号+目标类型)来强制转换类型

    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

    python 复制代码
    pip install pyyaml

1.YAML的读

  • 方法一:

    python 复制代码
    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)
  • 方法二:

    python 复制代码
    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的写

  • 方法一:(覆盖写入)

    python 复制代码
    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)
  • 方法二:(覆盖写入)

    python 复制代码
    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)
  • 方法三:(追加写入)

    python 复制代码
    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的清空

  • 方法一:

    python 复制代码
    # 清空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)
  • 方法二:

    python 复制代码
    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)) 实现数据驱动

  • 数据驱动

    python 复制代码
    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文件内容

    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文件内容

    python 复制代码
    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文件内容

    python 复制代码
    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.解决方法

  1. 找到项目下 venv/Lib/site-packages/allure_pytest/listener.py 源码文件,删除如图所示内容保存,重新启动项目查看allure测试报告结果

相关推荐
思则变14 小时前
[Pytest][Part 3]检测python package状态
pytest
百里图书11 天前
颠覆传统接口测试!用 Streamlit + SQLite + GPT 打造可视化自动化平台
自动化测试·测试开发·接口自动化测试·测试工具·接口测试·测试平台·python编程
漫谈网络12 天前
YAML 数据格式详解
python·yml·yaml·数据格式
cooldream200914 天前
pytest 框架详解与实战指南
pytest·测试
慕城南风14 天前
【pytest进阶】Pytest之conftest详解
pytest
编程小白gogogo15 天前
AI自动化测试速成(Pytest框架)
pytest
慕城南风15 天前
【pytest进阶】pytest详解及进阶使用
linux·服务器·pytest
川石教育22 天前
接口测试中缓存处理策略
软件测试·接口自动化测试·接口测试·缓存处理
Tom Boom22 天前
Pytest断言全解析:掌握测试验证的核心艺术
自动化测试·python·测试开发·pytest