pytest+uiautomation+allure 数据驱动桌面自动化项目搭建指南-yaml版本

本文基于 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 漏洞、依赖兼容问题

  1. 下载地址:Allure 官方 Releases,选择 2.41.0 版本 Windows 安装包

  2. 解压压缩包,将内部 bin 目录配置到系统环境变量

  3. 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. 优先级排序(从稳到次)

  1. AutomationId:唯一固定标识,适配动态窗口,优先使用

  2. Name:显示文本,适合固定文案按钮、标签

  3. 层级嵌套定位:父窗口+子控件,解决重名控件问题

  4. 模糊匹配:NameContains 适配动态变化文本

  5. foundIndex下标:适配同类型多个控件

3. 常用控件定位示例

python 复制代码
# 主窗口
auto.WindowControl(Name="应用窗口名")
# 输入框
auto.EditControl(AutomationId="inputId")
# 按钮
auto.ButtonControl(Name="确认")
# 文本标签
auto.TextControl(Name="账号")
# 复选框
auto.CheckBoxControl(Name="记住密码")

十一、数据驱动框架核心优势

  1. 低耦合易维护:测试数据独立存放,新增场景无需修改代码,仅编辑YAML文件

  2. 批量高效执行:单条用例逻辑,批量多组数据执行,大幅减少冗余代码

  3. 报告清晰:allure报告按用例名称区分每组数据执行结果,失败自动截图溯源

  4. 适配企业场景:可扩展登录、表单、弹窗、列表等多业务数据驱动场景

  5. 稳定性强:基于微软原生UI接口,无图像识别偏差,适配绝大多数Windows客户端

十二、常见问题解决方案

  • 元素定位失败:增大 searchDepth 层级、开启全局等待、先定位父窗口再找子控件

  • 用例执行过快报错:调整全局隐式等待时间,控件操作增加显性等待

  • allure报告为空 :执行 pytest 必须携带 \-\-alluredir 参数,清理旧数据

  • YAML数据读取失败:保证文件编码为utf-8,格式缩进规范

总结

本框架基于数据驱动模式 完成全套桌面自动化搭建,彻底区分 配置层、数据层、页面层、用例层,完全符合企业级自动化工程规范。可直接迁移适配ERP、后台客户端、办公软件等所有Windows桌面应用,只需替换控件定位和测试数据即可快速落地批量回归测试。

相关推荐
金玉满堂@bj1 小时前
pytest+uiautomation+allure+Excel 数据驱动桌面自动化
自动化·excel·pytest
晓蓝WQuiet1 小时前
《鸟哥的Linux私房菜》笔记 第七至十六章
linux·运维·笔记
山岚的运维笔记1 小时前
Bash 专业人员笔记 -- 第 11 章:`true`、`false` 和 `:` 命令
linux·运维·服务器·开发语言·笔记·学习·bash
ccyl011 小时前
UOS server 版(摩尔X300显卡)服务器安装显卡驱动
运维·服务器
comcoo1 小时前
阿里云百炼 + OpenClaw 打造超强自动化 AI
阿里云·自动化·云计算·openclaw安装包
海兰1 小时前
使用 OpenTelemetry 与 Elastic APM 追踪 MCP 服务器工具调用
运维·服务器·elasticsearch·wpf
青天飞叶1 小时前
2026年高性能推理标杆:DreamZero推理服务器深度解析(延迟低至1.2ms,吞吐量提升300%)
运维·服务器
IT大白鼠10 小时前
Linux进程与计划任务管理:技术详解与实战指南
linux·运维·服务器
临街的小孩11 小时前
Docker 容器内运行 ROS Noetic 图形界面(rqt_image_view)极简教程总结
运维·docker·容器