自动化测试基础——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测试报告结果

相关推荐
小张努力向上up1 天前
pytest使用报错(以及解决pytest所谓的“抑制print输出”)
pytest
测试界清流3 天前
Python自动化测试框架unittest与pytest的区别
开发语言·python·pytest
回家吃月饼3 天前
python中unittest框架和pytest框架区别
开发语言·python·pytest
MJH8275 天前
接口测试流程及测试点!
自动化测试·软件测试·selenium·单元测试·pytest·接口测试·压力测试
糖果店的幽灵6 天前
基于Python的自动化测试框架-Pytest总结-第一弹基础
服务器·python·pytest
测试界吖吖6 天前
【pytest】html报告修改和汉化
自动化测试·软件测试·python·功能测试·程序人生·html·pytest
潇潇说测试7 天前
Python+requests+pytest+excel+allure 接口自动化测试实战
自动化测试·软件测试·python·功能测试·程序人生·excel·pytest
Anthony_路人甲9 天前
pytest中的极其重要固件(request)的理解
python·pytest
牛油菠蘿包9 天前
Pytest--安装与入门
python·pytest
JAVA开发区9 天前
Python测试框架 pytest : 从零开始的完全指南
开发语言·python·pytest