SuperAPI AI 工具集

windows-desktop-e2e

测试与质量

查看项目

更新于 10-15 11:24

技能介绍

用途

windows-desktop-e2e 是一套面向 Windows 原生桌面应用的端到端(E2E)测试方案,使用 pywinauto 作为驱动层,底层依托 Windows UI Automation(UIA)——一个 Windows 内置、与框架无关的可访问性 API。覆盖范围包括 WPF、WinForms、Win32/MFC,以及 Qt 5.x / 6.x,其中 Qt 有独立章节说明。

适合在以下情况使用:

  • 为 Windows 原生桌面应用编写或运行 E2E 测试
  • 从零搭建桌面 GUI 测试套件
  • 诊断不稳定或失败的桌面自动化测试
  • 为现有应用补充可测试性(AutomationId、可访问名称)
  • 将桌面 E2E 集成到 CI/CD 流水线(GitHub Actions windows-latest)

不适合用于:Web 应用(应使用 Playwright 类方案)、Electron / CEF / WebView2 应用(HTML 层需要浏览器自动化而非 UIA)、移动应用(应使用 UIAutomator、XCUITest 等平台工具),以及不需要运行 GUI 的纯单元或集成测试。

主要能力

各框架的 UIA 质量对比(资料提供的表格归纳):

  • WPF:AutomationId 5/5,可靠性极佳,x:Name 直接映射为 AutomationId
  • WinForms:4/5,良好,AccessibleName 等同于 AutomationId
  • UWP / WinUI 3:5/5,极佳,微软完整支持
  • Qt 6.x:5/5,极佳,默认可访问性已开启,类名变为 Qt6*
  • Qt 5.15+:4/5,良好,Accessibility 模块有改进
  • Qt 5.7–5.14:3/5,一般,需要 QT_ACCESSIBILITY=1,objectName 需手动设置
  • Win32 / MFC:3/5,一般,控件 ID 可访问,文本匹配较常见

定位策略优先级:AutomationId > Name(文本)> ClassName + index > XPath,从稳定到脆弱依次递减。建议使用 Accessibility Insights for Windows(微软免费工具)检查 UIA 元素树。

等待模式:提供 wait_visible、wait_gone、wait_window 以及自定义轮询 wait_until,明确要求不要以 time.sleep() 作为主要同步手段。

产物管理:支持按需截图、窗口离屏或最小化时的全屏截图(pyautogui),以及用 ffmpeg 的 gdigrab 进行屏幕录制。

逐步骤追踪(可选):通过环境变量 E2E_TRACE=1 启用,为每个动作保存截图并写入 trace.jsonl;默认对输入的文本做脱敏(<redacted>),除非显式设置 E2E_TRACE_INCLUDE_TEXT=1。资料明确警告不要在登录或支付流程中开启该选项。

不稳定测试处理:提供 pytest.mark.skip(隔离)和 skipif(仅 CI 跳过)两种方式,并列出常见原因与修复(控件未就绪、窗口未聚焦、动画进行中、对话框时序、CI 显示未就绪、set_edit_text 抛出 NotImplementedError、控件存在但 wait_visible 超时等)。

测试隔离与沙箱:分为三层,推荐使用最轻量且满足需求的一层。

  • Tier 1 —— 文件系统隔离(默认,始终使用):每个测试通过 subprocess.Popen 与 Application.connect() 获得独立的 APPDATA / LOCALAPPDATA / TEMP 目录,由 pytest 的 tmp_path fixture 自动清理。

使用方式

安装(Python 3.8+,仅限 Windows):

pip install pywinauto pytest pytest-html Pillow pytest-timeout

屏幕录制为可选项,需安装 ffmpeg 并加入 PATH。

验证 UIA 可用性:

from pywinauto import Desktop
Desktop(backend="uia").windows()  # 列出所有顶层窗口

项目结构(页面对象模型):

tests/
├── conftest.py          # 应用启动 fixture,失败截图
├── pytest.ini
├── config.py
├── pages/
│   ├── __init__.py      # 导入所需
│   ├── base_page.py     # 定位器、等待、截图辅助
│   ├── login_page.py
│   └── main_page.py
├── tests/
│   ├── __init__.py
│   ├── test_login.py
│   └── test_main_flow.py
└── artifacts/           # 截图、视频、日志

可测试性改造:这是最具影响的一步——在编写测试前,为每个可交互控件赋予稳定的 AutomationId。

WPF 通过 XAML 中的 x:Name 自动成为 AutomationId:

<TextBox x:Name="usernameInput" />
<PasswordBox x:Name="passwordInput" />
<Button x:Name="btnLogin" Content="Login" />
<TextBlock x:Name="lblError" />

WinForms 设置 AccessibleName:

usernameInput.AccessibleName = "usernameInput";
passwordInput.AccessibleName = "passwordInput";
btnLogin.AccessibleName = "btnLogin";
lblError.AccessibleName = "lblError";

Win32 / MFC 的控件资源 ID 在 .rc 文件中会作为 AutomationId 字符串暴露(如 IDC_EDIT_USERNAME 对应 AutomationId "1001"),建议用 SetWindowText 设置 Name,并添加 IAccessible 以获得更丰富支持。

BasePage 核心方法包括:by_id / by_name / by_class 定位器,wait_visible / wait_gone / wait_window / wait_until 等待方法,click / type_text / get_text 动作方法,以及 screenshot 产物方法。type_text 在 set_edit_text 失败时会回退到 keyboard.send_keys(Qt 5.x 常见情况)。

配置通过环境变量注入:APP_PATH、APP_TITLE、LAUNCH_TIMEOUT、ACTION_TIMEOUT,均无内置默认路径。

pytest.ini 示例:

[pytest]
testpaths = tests
markers =
    smoke: fast smoke tests for critical paths
    flaky: known-unstable tests
addopts = -v --tb=short --html=artifacts/report.html --self-contained-html

启用逐步骤追踪:

E2E_TRACE=1 pytest tests/test_login.py -v
E2E_TRACE=1 E2E_TRACE_INCLUDE_TEXT=1 pytest ...

适用场景

  • 为 WPF / WinForms / Win32 / MFC / Qt 桌面应用构建回归测试套件
  • 在 CI(如 GitHub Actions windows-latest)中运行桌面 GUI 自动化
  • 调试间歇性失败的桌面自动化用例
  • 通过补充 AutomationId 提升应用的可自动化程度

限制与注意事项

资料中明确指出的限制:

  • 逐步骤追踪的 PII 风险:type_text 内容默认脱敏,绝不能在登录或支付流程设置 E2E_TRACE_INCLUDE_TEXT=1
  • 追踪开销:每个动作约增加 50–200ms,并产生每步一张 PNG;不建议在默认 CI 矩阵中启用,仅在专门的不稳定复现任务中使用
  • 产物膨胀:较长流程会产生数十 MB,应按需调整保留天数
  • 并行/重跑卫生:示例会追加写入 trace.jsonl 并使用类级计数器,重跑前应清空产物目录,并行测试需按 worker 使用独立产物目录
  • 覆盖率缺口:在 BasePage 之外执行的动作(测试代码中的原始 pywinauto 调用)不会被追踪
  • 各框架 UIA 支持质量不一,Qt 5.7–5.14 和 Win32/MFC 可靠性较低
  • 仅支持 Windows 平台,需要 Python 3.8+