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


所有评论(0)