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

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

数据驱动

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

三、使用Excel文件对测试用例做参数化

简介

在日常工作中,经常需要处理Excel 数据,例如读取、写入、修改、分析等等。

使用Excel文件存放测试用例,可以使得测试数据更加直观和易于管理。

Python 是一种强大的编程语言,可以通过其丰富的第三方库来操作 Excel。但是,直接使用原生库进行操作可能会比较繁琐,不够简洁高效。因此,可以封装一个工具类,来简化Excel的操作过程,提高开发、测试效率。

使用 openpyxl 模块处理 Excel 数据(若选择其他第三方库,其他模块自行学习了解);

示例:封装读取 Excel 文件方法
处理列数据

9、有些输入数据只需要一列,这种情况下只需要读取这一列的数据即可;

再写一个方法处理列数据,可参照处理行数据信息;

复制代码
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
from util_tools.logs_util.recordlog import logs
import os

class ExcelDataReader:

    def __init__(self, file_path):
        self.file_path = file_path
        abspath = os.path.abspath(self.file_path)

        if not os.path.isfile(abspath):
            raise FileNotFoundError(f'文件路径不存在:{abspath}')
        self.workbook = load_workbook(self.file_path, read_only=False)


    def read_entire_column(self, sheet_name='Sheet1', column_index=1):
        """
        获取Excel文件一整列的数据
        :param sheet_name: sheet页名称
        :param column_index: 要返回哪一列的数据,索引从1开始
        :return:
        """
        sheet = self.workbook[sheet_name]
        for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
            # 迭代器对象--获取的结果是单元格名称,例如:A1、A2、A3...)
            print(row)

    def close(self):
        self.workbook.close()

if __name__ == '__main__':
    exl = ExcelDataReader('../../data/login_test.xlsx')
    print(exl.read_entire_column())

9-1、 从运行结果可以查看到是一个元组类型;

复制代码
(<Cell 'Sheet1'.A1>,)
(<Cell 'Sheet1'.A2>,)
(<Cell 'Sheet1'.A3>,)
(<Cell 'Sheet1'.A4>,)
(<Cell 'Sheet1'.A5>,)
None

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

9-2、需要再循环这个迭代器对象,然后用循环的值去获取单元格的数据

复制代码
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
from util_tools.logs_util.recordlog import logs
import os

class ExcelDataReader:

    def __init__(self, file_path):
        self.file_path = file_path
        abspath = os.path.abspath(self.file_path)

        if not os.path.isfile(abspath):
            raise FileNotFoundError(f'文件路径不存在:{abspath}')
        self.workbook = load_workbook(self.file_path, read_only=False)


    def read_entire_column(self, sheet_name='Sheet1', column_index=1):
        """
        获取Excel文件一整列的数据
        :param sheet_name: sheet页名称
        :param column_index: 要返回哪一列的数据,索引从1开始
        :return:
        """
        sheet = self.workbook[sheet_name]
        for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
            # 循环迭代器对象,然后用循环的值去获取单元格的数据
            print(row[0].value)

    def close(self):
        self.workbook.close()

if __name__ == '__main__':
    exl = ExcelDataReader('../../data/login_test.xlsx')
    print(exl.read_entire_column())

9-3、 成功获取到第一列每一行的数据内容;

复制代码
username
admin123
admin111
admin123
admin
None

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

9-4、 定义一个列表把每一行数据存储起来;

复制代码
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
from util_tools.logs_util.recordlog import logs
import os

class ExcelDataReader:

    def __init__(self, file_path):
        self.file_path = file_path
        abspath = os.path.abspath(self.file_path)

        if not os.path.isfile(abspath):
            raise FileNotFoundError(f'文件路径不存在:{abspath}')
        self.workbook = load_workbook(self.file_path, read_only=False)


    def read_entire_column(self, sheet_name='Sheet1', column_index=1):
        """
        获取Excel文件一整列的数据
        :param sheet_name: sheet页名称
        :param column_index: 要返回哪一列的数据,索引从1开始
        :return:
        """
        column_data = []
        sheet = self.workbook[sheet_name]
        for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
            column_data.append(row[0].value)
        return column_data

    def close(self):
        self.workbook.close()

if __name__ == '__main__':
    exl = ExcelDataReader('../../data/login_test.xlsx')
    print(exl.read_entire_column())

9-5、 运行查看结果,已经能够成功获取到第一列的数据;

复制代码
['username', 'admin123', 'admin111', 'admin123', 'admin']

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

9-6、获取指定列数据(例如第二列)

复制代码
if __name__ == '__main__':
    exl = ExcelDataReader('../../data/login_test.xlsx')
    # 获取第二列的数据
    print(exl.read_entire_column(column_index=2))

运行结果:
['password', 123456, 123456, 111111, None]

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

9-7、添加 异常处理、日志、关闭文件 释放内容空间资源操作;

复制代码
# 引进 openpyxl 模块 load_workbook 方法
from openpyxl import load_workbook
# 引入 openpyxl 的一个异常处理
from openpyxl.utils.exceptions import InvalidFileException
# 引入日志
from util_tools.logs_util.recordlog import logs
# 引入os模块
import os

# 创建一个类
class ExcelDataReader:
    """
    读取Excel文件数据
    """

    # 写一个初始化构造方法
    def __init__(self, file_path):
        # 定义实例属性
        self.file_path = file_path
        # 写一下相对路径并返回出去
        abspath = os.path.abspath(self.file_path)

        # if判断 传进来的文件路径不存在(没有找到)时
        if not os.path.isfile(abspath):
            # 抛出异常提示
            raise FileNotFoundError(f'文件路径不存在:{abspath}')

        # read_only:控制工作簿是否以只读模式打开,若为True,工作簿以只读模式打开,不允许对工作簿进行修改
        self.workbook = load_workbook(self.file_path, read_only=False)

    def read_entire_row(self, sheet_name='Sheet1', row_index=1):
        """
        获取Excel文件一整行的数据
        :param sheet_name: sheet页名称
        :param row_index: 要返回哪一行的数据,索引从1开始
        :return:
        """
        # 调用上面初始化的打开这个文件的对象 self.workbook 列表里面是获取哪一行它的名称
        sheet = self.workbook[sheet_name]
        # 列表推导式
        rows_data = [cell.value for cell in sheet[row_index]]
        return rows_data

    def read_multiple_rows(self, sheet_name='Sheet1'):
        """
        读取Excel多行的数据,每一行数据组成一个列表
        :param sheet_name: sheet页名称
        :return: 返回list,例如:[['admin123','123456'],[],[],...]
        """
        try:
            # 在最外层定义一个空列表
            all_rows_data = []
            # 第一步跟上面一样,先拿到sheet这个对象
            sheet = self.workbook[sheet_name]
            # 调用 max_column 方法获取到最大的列数(行数 .max_row)
            max_col = sheet.max_column

            for row in sheet.iter_rows(min_row=1, max_row=sheet.max_row, min_col=1, max_col=max_col):
                # row 是一个迭代器对象--但是不是需要获取的结果
                # print(row)
                # 列表推导式
                row_data = [cell.value for cell in row]
                # 调用append方法追加每一行的数据
                all_rows_data.append(row_data)
            return all_rows_data
        except Exception as e:
            logs.error(f'读取所有行数据异常,原因为:{e}')
        finally:
            self.close()

    def read_entire_column(self, sheet_name='Sheet1', column_index=1):
        """
        获取Excel文件一整列的数据
        :param sheet_name: sheet页名称
        :param column_index: 要返回哪一列的数据,索引从1开始
        :return:
        """
        column_data = []
        try:
            sheet = self.workbook[sheet_name]
            for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
                column_data.append(row[0].value)
            return column_data
        except Exception as e:
            logs.error(f'读取整列数据异常,原因为:{e}')
        finally:
            self.close()
            
    def close(self):
        self.workbook.close()

# 调试查看
if __name__ == '__main__':
    # 实例化类--里面是文件路径
    exl = ExcelDataReader('../../data/login_test.xlsx')
    print(exl.read_entire_column(column_index=2))
获取某一个单元格的数据

10、读取某一个单元格的数据;

复制代码
# 引进 openpyxl 模块 load_workbook 方法
from openpyxl import load_workbook
# 引入 openpyxl 的一个异常处理
from openpyxl.utils.exceptions import InvalidFileException
# 引入日志
from util_tools.logs_util.recordlog import logs
# 引入os模块
import os

# 创建一个类
class ExcelDataReader:
    """
    读取Excel文件数据
    """

    # 写一个初始化构造方法
    def __init__(self, file_path):
        # 定义实例属性
        self.file_path = file_path
        # 写一下相对路径并返回出去
        abspath = os.path.abspath(self.file_path)

        # if判断 传进来的文件路径不存在(没有找到)时
        if not os.path.isfile(abspath):
            # 抛出异常提示
            raise FileNotFoundError(f'文件路径不存在:{abspath}')

        # read_only:控制工作簿是否以只读模式打开,若为True,工作簿以只读模式打开,不允许对工作簿进行修改
        self.workbook = load_workbook(self.file_path, read_only=False)

    def read_entire_row(self, sheet_name='Sheet1', row_index=1):
        """
        获取Excel文件一整行的数据
        :param sheet_name: sheet页名称
        :param row_index: 要返回哪一行的数据,索引从1开始
        :return:
        """
        try:
            # 调用上面初始化的打开这个文件的对象 self.workbook 列表里面是获取哪一行它的名称
            sheet = self.workbook[sheet_name]
            # 列表推导式
            rows_data = [cell.value for cell in sheet[row_index]]
            return rows_data
        except Exception as e:
            logs.error(f'读取Excel文件一整行的数据数据异常,原因为:{e}')
        finally:
            self.close()

    def read_multiple_rows(self, sheet_name='Sheet1'):
        """
        读取Excel多行的数据,每一行数据组成一个列表
        :param sheet_name: sheet页名称
        :return: 返回list,例如:[['admin123','123456'],[],[],...]
        """
        try:
            # 在最外层定义一个空列表
            all_rows_data = []
            # 第一步跟上面一样,先拿到sheet这个对象
            sheet = self.workbook[sheet_name]
            # 调用 max_column 方法获取到最大的列数(行数 .max_row)
            max_col = sheet.max_column

            for row in sheet.iter_rows(min_row=1, max_row=sheet.max_row, min_col=1, max_col=max_col):
                # row 是一个迭代器对象--但是不是需要获取的结果
                # print(row)
                # 列表推导式
                row_data = [cell.value for cell in row]
                # 调用append方法追加每一行的数据
                all_rows_data.append(row_data)
            return all_rows_data
        except Exception as e:
            logs.error(f'读取所有行数据异常,原因为:{e}')
        finally:
            self.close()

    def read_entire_column(self, sheet_name='Sheet1', column_index=1):
        """
        获取Excel文件一整列的数据
        :param sheet_name: sheet页名称
        :param column_index: 要返回哪一列的数据,索引从1开始
        :return:
        """
        column_data = []
        try:
            sheet = self.workbook[sheet_name]
            for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
                column_data.append(row[0].value)
            return column_data
        except Exception as e:
            logs.error(f'读取整列数据异常,原因为:{e}')
        finally:
            self.close()

    def read_cell_value(self, row_index, column_index, sheet_name='Sheet1'):
        """
        获取单元格的数据
        :param sheet_name: sheet页名称(sheet_name='Sheet1' 关键字参数放到形式参数后面就不会有报错提醒了)
        :param row_index: 行索引,从1开始
        :param column_index: 列索引,从1开始
        :return:
        """
        try:
            sheet = self.workbook[sheet_name]
            # 直接调用获取单元格方法 sheet.cell
            return sheet.cell(row=row_index, column=column_index).value
        except Exception as e:
            logs.error(f'读取单元格数据异常,原因为:{e}')
        finally:
            self.close()

    def close(self):
        """关闭文件操作(释放内存空间资源)"""
        self.workbook.close()

# 调试查看
if __name__ == '__main__':
    # 实例化类--里面是文件路径
    exl = ExcelDataReader('../../data/login_test.xlsx')
    print(exl.read_cell_value(row_index=4, column_index=2))

11、最后都加上异常处理;其他别的方法可以根据测试数据格式是否需要继续增加(根据自己的需求去自定义);

其他

12、 列表解包(列表亦可以通过元组解包的方式进行解包里面的元素);

复制代码
if __name__ == '__main__':
    # 实例化类--里面是文件路径
    exl = ExcelDataReader('../../data/login_test.xlsx')
    # print(exl.read_multiple_rows())

    data = ['admin123', '123456']
    username, password = data
    print(username, password)


# 运行结果
admin123 123456

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

13、若数据里面有三组数据,只想解包前面一组数据,后面两组还是一个列表;

复制代码
    data = ['admin123', '123456', '789']
    username, *password = data
    print(username, password)


# 运行结果
admin123 ['123456', '789']

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

Web UI 自动化测试数据驱动

未完待续。。。

相关推荐
DO_Community2 小时前
基于AI Agent模板:快速生成 SQL 测试数据
人工智能·python·sql·ai·llm·ai编程
岁月宁静2 小时前
从0到1:智能汇 AI 全栈实战,拆解多模态 AI 应用开发全流程
前端·vue.js·node.js
廾匸6402 小时前
语义化标签
前端·javascript·html
汪汪队立大功1233 小时前
selenium中执行javascript,是否等价于在浏览器console位置执行
javascript·selenium·测试工具
kewu89713 小时前
Postman 完全入门教程
测试工具·lua·postman
Rousson3 小时前
硬件学习笔记--89 MCU主频对Uart波特率影响及采样点
笔记·单片机·学习
烛阴3 小时前
隐式vs显式:解密C#类型转换的底层逻辑
前端·c#
Fantasydg3 小时前
AJAX JSON学习
前端·学习·ajax
越努力越幸运5083 小时前
AJAX 学习第一天:axios、HTTP 基础、serialize 插件
学习·http·ajax