Sparkle CodesSparkle
项目 / APP测试

Appium 自动化数据驱动:Excel、Pytest 参数化与断言分流

x
xpx
Mar 09, 2025
Editorial Insight
#Appium#Pandas#Pytest#数据驱动#测试开发

Appium 自动化数据驱动:Excel、Pytest 参数化与断言分流

系列导航

上一篇:Appium 登录自动化:Page、Object 与 Module 的拆分实践 入口页:用 POM 分层、关键字封装和数据驱动搭建 Appium 自动化测试框架 下一篇:Appium 自动化框架进阶:YAML、Allure 与读书屋搜索案例

只写一个“登录成功”用例并不难,真正有挑战的是把它扩展成一组可维护的场景:

  • 用户名为空;
  • 密码为空;
  • 用户名不存在;
  • 用户名密码不匹配;
  • 按钮置灰;
  • 登录成功。

如果每个场景都复制一份测试代码,后面会非常难维护。所以这篇聚焦数据驱动:让流程代码尽量不变,把变化放到数据里。

数据驱动的三步

当前材料里的思路很清楚:

  1. 先准备测试数据;
  2. 再读取并格式化;
  3. 最后通过 pytest.mark.parametrize 驱动测试执行。

用 Pandas 读取 Excel

示例里给了两种读法。

读成字典列表

PYTHON
def pandas_read_excel_dict(filepath, sheetname):
    data = pandas.read_excel(filepath, sheet_name=sheetname)
    data = data.where(data.notnull(), '')
    datadict = data.to_dict(orient='records')
    print(datadict)
    return datadict

读成普通列表

PYTHON
def pandas_read_excel_list(filepath, sheetname):
    data = pandas.read_excel(filepath, sheet_name=sheetname)
    data = data.fillna('')
    datalist = data.values.tolist()
    print(datalist)
    return datalist

为什么这里更推荐字典形式

因为字典形式更适合参数化测试:

  • 字段名更直观;
  • 后续可以直接用 caseinfo["casename"]、caseinfo["expectedresult"];
  • 测试数据和字段语义绑定更紧。
Tip

对入门阶段来说,Excel 很适合做第一版数据源。它足够直观,也方便非开发背景的测试同学维护。

接入 pytest.mark.parametrize

示例里的接法如下:

PYTHON
filepath = 'D:\\Apprun\\examples\\excel_test_data\\kaoyanbang.xlsx'
sheetname = 'Sheet2'
caseinfo = pandas_read_excel_dict(filepath, sheetname)
@pytest.mark.parametrize('caseinfo', caseinfo)
def test_login_success(abcd, caseinfo):
    driver = abcd
    allure.dynamic.title(caseinfo["casename"])
    casedata = eval(caseinfo["allparams"])

这段代码的关键点有三个:

  • Excel 每一行对应一条用例;
  • allure.dynamic.title() 可以让报告标题随着数据变化;
  • 同一套流程代码会被多次执行,但每次参数不同。

参数化之后,断言为什么也要分流

参数化并不意味着所有用例都走同一种断言。

示例里就做了分支处理:

PYTHON
if caseinfo['caseid'] in ['login001', 'login005']:
    ele = wait_element(driver, widgetToast)
    assert ele.text in eval(caseinfo['expectedresult'])
elif caseinfo['caseid'] in ['login004', 'login002', 'loging003']:
    ele = get_element(driver, loginCodeLoginBtn)
    assert ele.get_attribute('enabled') == False

这里体现了数据驱动真正有价值的地方:

  • 流程可以相同;
  • 预期结果不一定相同;
  • 不同场景的断言方式也可能完全不同。

这套设计适合哪些断言

在当前材料里,至少已经覆盖了三类:

  • 成功场景:断言“跳过”按钮文本;
  • 错误提示场景:断言 Toast;
  • 表单非法场景:断言登录按钮 enabled == False。

这说明数据驱动不是简单地“多跑几组输入”,而是让同一个业务流程可以承载不同的验证目标。

实战里最容易踩的坑

Warning

数据驱动真正难的地方往往不在 parametrize 本身,而在数据格式、断言选择和边界处理。

常见问题包括:

  • pytest.mark.parametrize 拼写错误;
  • Windows 路径转义处理不对;
  • find_element 和 find_elements 搞混;
  • Toast 没有显式等待就去断言;
  • enabled 属性返回值类型没有实际确认;
  • 测试数据字段命名不稳定,后期很难维护。

当前示例还值得进一步优化的地方

虽然这套代码足以表达思路,但如果往更稳的工程实践走,还有两个点值得改:

  1. eval(caseinfo["allparams"]) 这在教学示例里方便,但真实项目里更推荐 JSON 或更安全的解析方式。
  2. Excel 字段约定 最好尽早固定清楚,比如:caseid、casename、allparams、expectedresult 各自到底存什么。

小结

数据驱动的核心,不是把 Excel 接进来,而是把“变化”从代码中抽离出来。这样新增场景时,优先改的是数据;只有当流程本身变化时,才需要改测试代码。

继续阅读:Appium 自动化框架进阶:YAML、Allure 与读书屋搜索案例

BACK TO BLOG
The End of Interaction