本文基于 pytest + uiautomation + allure 技术栈,搭建一套数据驱动(DDT)的 Windows 桌面应用自动化测试框架。彻底实现测试数据与业务代码分离,适配多组测试数据、批量回归测试,兼容企业级桌面客户端自动化场景,支持精美可视化测试报告生成。
一、技术栈说明
-
uiautomation:微软原生 Windows UI 自动化库,稳定无依赖,适配所有标准桌面控件
-
pytest:测试用例管理、执行、断言、数据驱动参数化核心框架
-
allure-pytest:生成交互式可视化测试报告,支持失败截图、用例分级、步骤展示
-
数据驱动模式:独立存放测试数据,代码只写一次,批量执行多组测试场景,易维护、可复用
二、完整环境准备
1. 安装核心依赖库
bash
# 安装自动化核心库、报告库、数据处理库
pip install pytest uiautomation allure-pytest pyyaml
2. Allure 报告工具安装(必备)
适配最新稳定版 Allure 2.41.0,修复旧版 XSS 漏洞、依赖兼容问题
-
下载地址:Allure 官方 Releases,选择 2.41.0 版本 Windows 安装包
-
解压压缩包,将内部
bin目录配置到系统环境变量 -
cmd 验证安装是否成功
bash
allure --version
三、数据驱动版项目目录结构(工程化标准)
新增 data 测试数据目录,实现代码、数据、页面、用例完全解耦
plain
desktop_automation/
├── config/ # 全局配置目录
│ └── setting.py # 应用路径、等待时间、全局配置
├── data/ # 【数据驱动核心】测试数据目录
│ └── notepad_data.yml # yml格式测试用例数据
├── page/ # PO页面对象层
│ ├── base_page.py # 基础公共操作封装
│ └── notepad_page.py # 业务页面控件&方法
├── testcase/ # 测试用例层(纯逻辑,无硬编码数据)
│ └── test_notepad.py # 数据驱动测试用例
├── report/ # 自动生成测试报告
│ ├── temp/ # allure原始数据
│ └── html/ # 最终可视化报告
├── conftest.py # pytest全局钩子、失败截图
└── pytest.ini # pytest全局配置
四、全局配置文件
config/setting.py
python
# 被测应用配置
APP_PATH = "notepad.exe"
# 全局隐式等待时间
IMPLICIT_WAIT = 3
# 测试数据文件路径
TEST_DATA_PATH = "./data/notepad_data.yml"
五、数据驱动核心:测试数据文件
采用 YAML 存储测试数据,支持多组场景、测试描述、预期结果,无需修改代码即可新增/删除用例
data/notepad_data.yml
yaml
# 记事本输入测试-数据驱动
test_input_data:
- case_name: "普通文本输入测试"
input_content: "pytest+uiautomation 桌面自动化"
expect_content: "pytest+uiautomation 桌面自动化"
- case_name: "特殊符号输入测试"
input_content: "测试123!@#$%^&*()"
expect_content: "测试123!@#$%^&*()"
- case_name: "空内容输入测试"
input_content: ""
expect_content: ""
- case_name: "长文本输入测试"
input_content: "数据驱动自动化测试,代码与数据分离,高效维护用例"
expect_content: "数据驱动自动化测试,代码与数据分离,高效维护用例"
六、PO页面封装层
1. 基础公共页面 page/base_page.py
封装所有桌面应用通用操作,统一等待、点击、输入、截图、元素判断方法,所有业务页面继承此类
python
import uiautomation as auto
import time
from config.setting import IMPLICIT_WAIT
class BasePage:
def __init__(self):
# 全局控件查找间隔,防止操作过快报错
auto.SetGlobalSearchInterval(0.1)
auto.SetGlobalSearchTimeout(IMPLICIT_WAIT)
self.app_window = None
def start_app(self, app_path: str):
"""启动桌面应用"""
auto.Run(app_path)
time.sleep(IMPLICIT_WAIT)
def get_window(self, window_name: str):
"""定位应用主窗口"""
self.app_window = auto.WindowControl(Name=window_name, searchDepth=1)
return self.app_window
def close_app(self):
"""关闭应用窗口"""
if self.app_window and self.app_window.Exists(0):
self.app_window.Close()
time.sleep(1)
def click_control(self, control, wait_time=1):
"""通用控件点击方法"""
if control.WaitForExist(wait_time):
control.Click()
time.sleep(0.5)
def input_text(self, control, text: str, wait_time=1):
"""通用文本输入方法"""
if control.WaitForExist(wait_time):
control.SendKeys(text)
time.sleep(0.5)
def get_control_text(self, control):
"""获取控件文本内容"""
if control.WaitForExist(1):
return control.Name if control.Name else control.DocumentText
return ""
2. 业务页面 page/notepad_page.py
仅封装页面控件和业务方法,不写测试数据、不写断言,完全解耦
python
import uiautomation as auto
from page.base_page import BasePage
class NotePadPage(BasePage):
def __init__(self):
super().__init__()
# 页面控件定位
self.window_name = "无标题 - 记事本"
self.edit_area = auto.EditControl(searchDepth=2)
def input_edit_content(self, content: str):
"""记事本输入指定内容"""
self.input_text(self.edit_area, content)
def get_edit_content(self):
"""获取记事本输入框内容"""
return self.get_control_text(self.edit_area)
七、数据驱动测试用例层
核心改造点:通过 pytest 读取 YAML 数据,参数化批量执行用例,代码复用,数据灵活配置
testcase/test_notepad.py
python
import pytest
import yaml
from page.notepad_page import NotePadPage
from config.setting import APP_PATH, TEST_DATA_PATH
# 读取YAML测试数据
def get_test_data():
with open(TEST_DATA_PATH, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
return data["test_input_data"]
class TestNotePadDDT:
# 全局前置:启动应用
def setup_class(self):
self.page = NotePadPage()
self.page.start_app(APP_PATH)
self.page.get_window(self.page.window_name)
# 全局后置:关闭应用
def teardown_class(self):
self.page.close_app()
# 数据驱动参数化执行
@pytest.mark.parametrize("case", get_test_data(), ids=lambda x: x["case_name"])
def test_notepad_input_ddt(self, case):
"""记事本多场景数据驱动输入测试"""
# 从数据文件读取参数
input_content = case["input_content"]
expect_content = case["expect_content"]
# 执行业务操作
self.page.input_edit_content(input_content)
actual_content = self.page.get_edit_content()
# 断言校验
assert actual_content == expect_content, f"用例失败:预期{expect_content},实际{actual_content}"
八、全局钩子与配置
conftest.py(失败自动截图+allure绑定)
python
import pytest
import allure
import uiautomation as auto
# 用例失败自动截图并嵌入allure报告
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
# 仅用例执行阶段失败时截图
if report.when == "call" and report.failed:
try:
pic = auto.CaptureToImage()
allure.attach(pic, name="失败截图", attachment_type=allure.attachment_type.PNG)
except Exception as e:
print(f"截图失败:{str(e)}")
pytest.ini(全局运行配置)
ini
[pytest]
# 用例扫描路径
testpaths = testcase
# 用例文件命名规则
python_files = test_*.py
# 测试类命名规则
python_classes = Test*
# 测试方法命名规则
python_functions = test_*
# 运行参数 + allure原始数据输出路径
addopts = -vs --alluredir=./report/temp --clean-alluredir
九、项目运行命令
1. 执行所有数据驱动用例
bash
pytest
2. 生成并打开Allure可视化报告
bash
# 生成静态报告
allure generate ./report/temp -o ./report/html --clean
# 打开报告页面
allure open ./report/html
十、uiautomation元素定位核心方法
1. 定位工具(必备)
-
系统自带工具:
C:\\Program Files \(x86\)\\Windows Kits\\10\\bin\\x64\\inspect\.exe -
轻量化工具:命令行执行
python \-m uiautomation\.inspect -
核心抓取属性:AutomationId(最优)、Name、ClassName、ControlType
2. 优先级排序(从稳到次)
-
AutomationId:唯一固定标识,适配动态窗口,优先使用
-
Name:显示文本,适合固定文案按钮、标签
-
层级嵌套定位:父窗口+子控件,解决重名控件问题
-
模糊匹配:NameContains 适配动态变化文本
-
foundIndex下标:适配同类型多个控件
3. 常用控件定位示例
python
# 主窗口
auto.WindowControl(Name="应用窗口名")
# 输入框
auto.EditControl(AutomationId="inputId")
# 按钮
auto.ButtonControl(Name="确认")
# 文本标签
auto.TextControl(Name="账号")
# 复选框
auto.CheckBoxControl(Name="记住密码")
十一、数据驱动框架核心优势
-
低耦合易维护:测试数据独立存放,新增场景无需修改代码,仅编辑YAML文件
-
批量高效执行:单条用例逻辑,批量多组数据执行,大幅减少冗余代码
-
报告清晰:allure报告按用例名称区分每组数据执行结果,失败自动截图溯源
-
适配企业场景:可扩展登录、表单、弹窗、列表等多业务数据驱动场景
-
稳定性强:基于微软原生UI接口,无图像识别偏差,适配绝大多数Windows客户端
十二、常见问题解决方案
-
元素定位失败:增大 searchDepth 层级、开启全局等待、先定位父窗口再找子控件
-
用例执行过快报错:调整全局隐式等待时间,控件操作增加显性等待
-
allure报告为空 :执行 pytest 必须携带
\-\-alluredir参数,清理旧数据 -
YAML数据读取失败:保证文件编码为utf-8,格式缩进规范
总结
本框架基于数据驱动模式 完成全套桌面自动化搭建,彻底区分 配置层、数据层、页面层、用例层,完全符合企业级自动化工程规范。可直接迁移适配ERP、后台客户端、办公软件等所有Windows桌面应用,只需替换控件定位和测试数据即可快速落地批量回归测试。