使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 23--数据驱动--参数化处理 Yaml 文件

测试学习记录,仅供参考!

数据驱动

结合 pytest 框架参数化处理对测试用例做参数化;介绍 Json 格式文件、yaml 格式文件、Excel 格式文件 三种文件方式去做测试用例参数化;

二、使用yaml文件对测试用例做参数化

Yaml是一种简洁的非标记语言,Yamll以数据为中心,使用空白、缩进、分行组织数据,从而使得表示更加简洁意读。由于实现简单,解析成本很低,Yaml特别适合在脚本语言中使用,Yaml是专门用来写配置文件的语言,非常简洁强大,远比JSON格式方便,一般使用 yaml 文件做数据配置比较多,但也有做参数化的,在接口自动化测试中,可用作配置文件,配置一些服务器域名、mysql配置、登录信息、toekn等数据信息,方便快速读取,像是接口的一些相关信息,都是用 yaml 文件去管理的;

Yaml 文件语法特点(规则):

1、大小写敏感,英文字母区分大小写;

2、使用缩进表示层级关系;

3、缩进时不允许使用Tab键,只允许使用空格;

4、缩进的空格数目不重要亦不固定,只需要相同层级的元素左侧对齐即可;

5、文件中的字符串不需要使用引号标注,但若字符串包含有特殊字符则需用引号标注;

6、key值前面带**-**表示这组数据是一个列表类型,两组数据的-属于同级关系的话,数据存在一个列表里面;

7、Yaml 文件中的注释标识符为 # 井号,在所在行最前面增加标识符 # 即为注释本行;

Yaml 文件数据结构

对象:键值对的集合(简称 "映射或字典"),包含key和 value;

键值对中间使用冒号 ":" 结构表示,冒号与值之间需用空格分隔;

key:描述对象属性的字符串;

value:可以是纯量、对象结合、数组;

数组:一组按序排列的值(简称 "序列或列表")

数组前加有 "-" 符号,以 - 开头的行表示构成一个数组,符号与值之间需用空格分隔;

纯量(scalars):单个的、不可再分的值(例如:字符串、bool值、整数、浮点数、时间、日期、Null等)

Yaml 安装

安装 yaml 库

复制代码
pip install pyyaml
代码演示

1、在项目根目录 data 目录文件下新建名称为 login.yaml(login.yml 两种格式均行 ) 的 yaml 文件;

在 yaml 文件中列表以 "-"(一个横杠)展示,每一组数据以逗号分隔;

复制代码
- admin123,123456
- admin123456,123456
- admin123,123456789
- admin123,

yaml 文件亦是键值对的方式,但是需要注意冒号":"后面要有一个空格,不然就会报错;且键值不能重复;

2、在 handle_data 软件包下新建名称为 readYaml.py(专门处理 yaml 文件) 的 Python 文件;

第一步,先导入 yaml 模块(如果导入不了 yaml 模块,需要先去安装 yaml 库)

直接写一个函数 def read_yaml(file_path): 里面传一个参数(读取哪个 yaml 文件的路径);

复制代码
import yaml

def read_yaml(file_path):
    """
    读取yaml文件的数据
    :param file_path: yaml文件路径
    :return: 返回列表类型,列表里面是元组数组
    """
    with open(file_path, 'r', encoding='utf-8') as file:
        # 添加这个 Loader=yaml.FullLoader 参数后不会在控制台输出警告信息
        data = yaml.load(file, Loader=yaml.FullLoader)
    return data

# 调用函数调试--相对路径
res = read_yaml('../../data/login.yaml')
print(res)

3、运行 readYaml.py 文件查看结果,最外层是一个列表,里面每一组是一个字符串;

复制代码
['admin123,123456', 'admin123456,123456', 'admin123,123456789', 'admin123,']

进程已结束,退出代码为 0

4、这种格式在 test_login.py 文件中做参数化时还需要处理才能拿到每一个数据,与其在 test_login.py 文件中做处理,还是直接在 readYaml.py 读取 yaml 文件中做处理更方便;

5、优化 readYaml.py 文件;

1)、 for data_str in data: 首先,循环一下列表中的每组数据,因为每组数据是字符串类型;

2)、if data_str is not None: 加一个判断,防止 yaml 文件中有空数据的场景;

3)、data_str.split(',') 调用指定的方法,通过 ,逗号 对每一组数据进行分割;

4)、tuple(data_str.split(',')) 分割之后转换成元组类型

5)、data_tuple = tuple(data_str.split(',')) 把结果返回出去;

此时,若 return data_tuple 调式查看结果是只返回了一组数据(最后一组);

6)、因为需要返回全部的数据信息,所以在最外层定义一个 data_list_tuple = [] 空的列表;

7)、data_list_tuple.append(data_tuple) 把所有数据追加到这个 data_list_tuple 空列表中;

8)、return data_list_tuple 这时候把最外层这个列表给返回出去即可;

复制代码
import yaml
from nibabel.testing import data_path

def read_yaml(file_path):
    """
    读取yaml文件的数据
    :param file_path: yaml文件路径
    :return: 返回列表类型,列表里面是元组数据,如:[('admin123','123456'),(),(),()......]
    """
    # 在最外层定义一个空列表
    data_list_tuple = []
    with open(file_path, 'r', encoding='utf-8') as file:
        # 添加这个 Loader=yaml.FullLoader 参数后不会在控制台输出警告信息
        data = yaml.load(file, Loader=yaml.FullLoader)
        for data_str in data:
            if data_str is not None:
                data_tuple = tuple(data_str.split(','))
                data_list_tuple.append(data_tuple)
    return data_list_tuple

# 调用函数调试--相对路径
res = read_yaml('../../data/login.yaml')
print(res)

6、运行 readYaml.py 文件查看结果是符合要求的(是需要的数据格式);

复制代码
[('admin123', '123456'), ('admin123456', '123456'), ('admin123', '123456789'), ('admin123', '')]

进程已结束,退出代码为 0

7、引入日志,优化 readYaml.py 文件;

像这种读取文件的操作最好是加上'异常处理'和'日志打印';

复制代码
import yaml
from util_tools.logs_util.recordlog import logs

def read_yaml(file_path):
    """
    读取yaml文件的数据
    :param file_path: yaml文件路径
    :return: 返回列表类型,列表里面是元组数据,如:[('admin123','123456'),(),(),()......]
    """
    try:
        data_list_tuple = []
        with open(file_path, 'r', encoding='utf-8') as file:
            # 添加这个 Loader=yaml.FullLoader 参数后不会在控制台输出警告信息
            data = yaml.load(file, Loader=yaml.FullLoader)
            for data_str in data:
                if data_str is not None:
                    data_tuple = tuple(data_str.split(','))
                    data_list_tuple.append(data_tuple)
        return data_list_tuple
    except Exception as e:
        logs.error(f'读取yaml文件异常,异常原因为:{e}')

8、把读取 yaml 文件的写完了之后怎么在测试用例里面用到做参数化呢?

9、优化 test_login.py 文件;

1)、 导包引入读取 yaml 文件的 def read_yaml(file_path): 方法;

2)、使用 @pytest.mark.parametrize() 装饰器做参数化,第一个(参数)是接收后面一个可迭代参数(第二个参数)内容的参数,第一个参数 data(自定义名称),第二个参数 通过调用读取 yaml 文件 read_yaml() 方法,里面传路径文件参数;与读取 json 文件一样,这里更改读取方法即可,其他不动(自行更改代码);

复制代码
import pytest
from selenium.webdriver.common.by import By
from time import sleep
from pageObject.login_page.login_page import LoginPage
# from util_tools.handle_data.operateJson import read_json
from util_tools.handle_data.readYaml import read_yaml

class TestLogin:

    # 使用参数化实现一条测试用例跑多种场景--可迭代对象里面有多少组数据就跑多少次测试用例
    @pytest.mark.parametrize('data', read_yaml('./data/login.yaml'))
    # 用一个 data(需与上面保持一致) 参数去接收参数化数据
    def test_login_success(self, get_driver, data):
        # 进行元组解包--通过两个参数去接收元组中的每一组数据
        username, password = data
        # 传浏览器对象--再把结果返回
        login_page = LoginPage(get_driver)
        # 直接调用页面类中的 login 操作--里面需要输入两个参数(参数化传两个参数)
        login_page.login(username, password)
        # 断言结果
        success_ele = get_driver.find_element(By.XPATH, '//*[@id="ECS_MEMBERZONE"]/font/font')
        assert success_ele != ''
        sleep(2)

10、运行 run.py 主函数文件查看执行结果;

未完待续。。。

相关推荐
晨尘光2 小时前
【pycharm 创建一个线程,在线程函数中增加的日志打印,日志打印了,但是打断点进不去】
ide·python·pycharm
databook3 小时前
manim边做边学--文字创建销毁的打字机效果
后端·python·动效
小艳加油3 小时前
AI+Python近红外光谱分析机器学习与深度学习实战,覆盖提示词撰写、数据预处理、回归/神经网络/集成学习/迁移学习/可解释性可视化等
python·近红外光谱分析·多元线性回归
s11show_1633 小时前
ruoyi-app学习路线
学习
安全系统学习3 小时前
自学网络安全学习的误区和陷阱
数据库·学习·安全·web安全·网络安全·安全架构
领创工作室3 小时前
Linux基础指令-Linux学习笔记(1)
linux·笔记·学习
清钟沁桐3 小时前
mlir 编译器学习笔记之五 -- 开发避坑
笔记·学习·mlir
仰望—星空3 小时前
MiniEngine学习笔记 : RootSignature
windows·笔记·学习
JamSlade4 小时前
SSO登录验证设计要点细节(以微软 Microsoft SSO为例) 基于react python
python·react.js·microsoft