一、数据驱动简介

DDT是一种软件测试方法,通过外部数据源(如Excel、CSV、数据库等)驱动测试用例的执行。它的核心思想是将测试数据与测试逻辑分离,从而提高测试的灵活性和可维护性。

1. DDT 的核心概念
测试数据与逻辑分离:

测试逻辑是固定的,而测试数据可以从外部文件或数据库中动态加载。

数据可以是输入参数、预期结果或配置信息。

数据源:

常见的数据源包括:CSV文件、Excel文件、JSON文件、数据库、API等。

测试用例动态生成:

根据数据源中的每一行数据,动态生成一个测试用例。

2. DDT 的优点
提高测试覆盖率:

通过多组数据测试同一逻辑,覆盖更多场景。

减少代码重复:

测试逻辑只需编写一次,数据可以动态加载。

易于维护:

当测试数据变化时,只需修改数据源,而无需修改测试代码。

支持复杂场景:

可以通过大量数据组合测试边界条件和异常情况。

二、读取Excel数据文件

        这里使用的库是openpyxl,同时也可以使用xlrd

        1.安装openpyxl库、pytest
pip install openpyxl
pip install pytest
        2.详情操作

                实际项目根目录下有data.xlsx文件

def get_data():
    filename = 'data.xlsx' 
    wb = load_workbook(filename) # 加载Excel文件,返回Workbook对象
    # sheet = wb.active # 获取活动工作表(默认第一个Sheet)
    sheet = wb['Sheet2']  # 明确指定 Sheet2 表
    # min_row=2表示从第2行开始迭代(默认从第 1 行开始)
    # values_only返回单元格的值,直接得到数据(如 "tom" 而非 <Cell 'Sheet1'.A1>)
    return [list(row) for row in sheet.iter_rows(min_row=2, values_only=True)]

@pytest.mark.parametrize('username,age,expected_true',get_data())
def test_03(username,age,expected_true):
    print(username,age,expected_true)

三、读取CSV数据文件

        方式一:使用python内置模块

        1.导入python内置模块csv

        2.详细操作

                实际在项目对应目录下有对于test.csv文件

def get_data():
    # 使用with打开文件,文件会自动关闭,不需要手动调用 file.close()
    with open('../../testcases/ddt/test.csv') as f:
        # 读取文件内容
        lst = csv.reader(f)
        # 跳过表头
        header = next(lst)
        # 将每行转换为元组,因为parametrize需要序列的序列
        return [tuple(row) for row in lst]

@pytest.mark.parametrize('username,age,expected_true',get_data())
def test_02(username,age,expected_true):
    print(username,age,expected_true)
        方式二: 使用pandas库

                1.下载pandas库

pip install pandas

                2.详细操作

# 使用pandas库来读取CSV文件
# values将 DataFrame 转换为 NumPy 数组
# tolist将 NumPy 数组转换为 Python 原生列表
# pd.read_csv() 默认会自动将 CSV 文件的第一行作为表头(列名)读取,
# 但通过 .values.tolist() 转换时,表头会被自动忽略,仅保留数据行

@pytest.mark.parametrize('username,age,expected_true',pd.read_csv('../../testcases/ddt/test.csv').values.tolist())
def test_01(username,age,expected_true):
    print(username,age,expected_true)

四、读取数据库——以MySQL为例

        1.下载mysqlclient
pip install mysqlclient
        2.连接对应数据库
def get_connection():
    # 数据库配置信息换成自己的
    try:
        return MySQLdb.connect(
            user = 'root',
            password = '123456',
            host = 'localhost',
            port = 3306,
            charset='utf8mb4',
            db = 'bus'
        )
    except Exception as e:
        print(f"数据库连接错误,{e}")
        raise
        3.详情操作
def get_data(query_sql):
    try:
        # 2. 获取数据库连接
        conn = get_connection()
        # 3. 使用上下文管理器创建游标(自动管理资源)
        with conn.cursor() as cursor:
            # 4. 执行SQL查询
            cursor.execute(query_sql)
            # 5. 提取所有行数据,并将每行转换为元组
            # cursor.fetchall()返回所有行的数据
            return [tuple(row) for row in cursor.fetchall()]
    except Exception as e:
        print(f"数据库查询错误,{e}")
        # 重新抛出异常,避免静默失败
        raise
    finally:
        # 7. 确保连接关闭(无论是否发生异常)
        if 'conn' in locals() and conn.open:
            conn.close()

@pytest.mark.parametrize('id,username,phone,money',get_data('select id,username,phone,money from b_user'))
def test_01(id,username,phone,money):
    print(id,username,phone,money)

五、读取JSON数据文件

               1.json数据文件

[
  {
    "username": "tom",
    "age": "18",
    "expected_true": "True"
  },
  {
    "username": "lisa",
    "age": "22",
    "expected_true": "True"
  },
  {
    "username": "kitty",
    "age": "25",
    "expected_true": "False"
  }
]

               2.详细操作

def get_data():
    with open('../../testcases/ddt/test.json') as f:
        # 用于从文件对象中读取JSON数据,并将其解析为Python对象。
        # loads用于将JSON格式的字符串解析为Python对象
        data = json.load(f)
        return [(item['username'],item['age'],item['expected_true']) for item in data]
            

@pytest.mark.parametrize('username,age,expected_true',get_data())
def test_02(username,age,expected_true):
    print(username,age,expected_true)

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐