PowerToys FancyZones 编辑器发布回归清单:手工用例向 UI 自动化测试迁移的完整覆盖指南
【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys
FancyZones 是 Microsoft PowerToys 中负责窗口分区布局的核心模块,其编辑器支持模板布局、画布/网格自定义布局、多显示器分配与快捷键切换等能力。本篇文章以仓库内 FancyZonesEditor.UITests/release-test-checklist.md 为骨架,完整讲解这份"发布前回归测试清单"如何把原本由人手工执行的编辑器测试用例逐步转化为可在 CI 与 Release pipeline 中自动运行的 UI 测试,并结合同目录下的测试源码,说明每一项清单背后的自动化落点、测试数据模型与运行前提。读完本文,你将掌握 FancyZones 编辑器 UI 自动化回归的完整场景集、每个场景对应的测试文件,以及如何在本机用 WinAppDriver + MSTest 复跑这些用例。
一、清单文档的定位与阅读方式
这份文档存放在测试工程目录src/modules/fancyzones/FancyZonesEditor.UITests/下,是一份迁移进度跟踪清单,其核心目标在文档开头写得非常明确:
- 凡是此前由 PowerToys 维护者手工执行的 FancyZones 编辑器测试用例,都要转换为 UI 测试;
- 转换后的 UI 测试要在 CI 与 Release pipeline 中持续运行,替代"发布前人工点一遍"的回归方式;
- 文档通过一组可勾选的
- [ ]条目记录每个用例的迁移状态。
文档内容分为两大部分:第一部分是"由前维护者执行过的既有手工用例",覆盖启动、新建、复制、删除、编辑、分配、默认布局等编辑器主流程;第二部分是"补充的 UI 测试场景",粒度更细,聚焦保存/取消语义、删除副作用、UI 初始化状态、数据文件持久化与首次启动等边界行为。
值得注意的是,清单条目(例如Launch Host File Editor)显然沿用了通用回归清单模板的措辞,实际被测对象是FancyZones 编辑器——对照同目录测试类名与文档上下文即可确认。因此阅读本清单时应以"编辑器功能维度"理解各条目的真实意图。
二、被测核心:FancyZones 编辑器与其配置数据模型
要读懂回归清单,先要理解编辑器所操作的对象。围绕本清单,以下几个概念是反复出现的高频词:
2.1 布局类型与模板
编辑器内置的模板布局类型在 TestConstants.cs 中被逐一列出,测试用固定名称索引这些模板卡片:
| 布局类型 | 界面显示名称 |
|---|---|
| Blank | No layout |
| Focus | Focus |
| Rows | Rows |
| Columns | Columns |
| Grid | Grid |
| Priority Grid | Priority Grid |
模板布局是"参数化的",可调参数(见LayoutTemplates.TemplateLayoutWrapper)包括:
Type:布局类型;ZoneCount:分区数量;ShowSpacing/Spacing:是否启用并设置分区间距;SensitivityRadius:拖动窗口靠近分区时高亮命中相邻分区的灵敏度半径(清单中写作 "distance to highlight adjacent zones")。
模板基础上,用户还能通过"基于模板创建自定义布局"得到一份可独立编辑的副本;而自定义布局按编辑方式分为两类,清单对它们分别出用例:
- Canvas(画布)布局:自由放置、缩放、新增与删除分区(zone);
- Grid(网格)布局:对分区做拆分(split)、合并(merge)、拖动分隔条调整大小(resize/move splitter)。
2.2 配置数据文件:清单反复断言的对象
编辑器的所有状态都持久化为 JSON 文件,路径集中定义在 FancyZonesEditorCommon/Data/FancyZonesPaths.cs,位于%LOCALAPPDATA%\Microsoft\PowerToys\FancyZones下:
applied-layouts.json:各显示器/虚拟桌面当前应用的布局与参数;custom-layouts.json:用户自定义布局集合;layout-templates.json:内置模板布局的当前参数配置;layout-hotkeys.json:布局切换快捷键;default-layouts.json:横向/纵向显示器各自的默认布局;editor-parameters.json:编辑器启动参数(由调用方写入,含显示器枚举信息)。
测试辅助类 FancyZonesEditorFiles.cs 为上述每个文件(外加应用分区历史)各持有一个IOTestHelper读写器,并提供Restore()在用例执行前统一还原初始数据——清单中"applied-layouts.json 保留未连接设备信息""首次启动时不存在各类 json"等条目,正是围绕这些文件展开的持久化回归场景。
2.3 编辑器由外部参数驱动
编辑器本身是独立进程,由 PowerToys 主程序按需拉起,并通过editor-parameters.json传入本次会话的显示器快照。测试中常见的EditorParameters.ParamsWrapper字段(见 EditorParameters.cs)包括ProcessId、SpanZonesAcrossMonitors,以及每个显示器条目的MonitorInstanceId、MonitorSerialNumber、MonitorNumber、VirtualDesktop、Dpi、屏幕与工作区坐标尺寸、IsSelected等。UI 测试正是通过预先写入带 1~2 台显示器(含不同 DPI、不同选中状态)的参数文件,来驱动编辑器渲染出可点击的"Monitor 1 / Monitor 2"卡片,从而自动化验证"为每台显示器分配布局"等回归场景。
三、第一部分:既有手工回归用例及其自动化落点
清单第一部分把维护者以往发布前手工验证的编辑器主流程拆成十余条,以下逐组说明每条的真实含义,以及在FancyZonesEditor.UITests工程中对应的测试落点。
3.1 启动编辑器:从设置入口与快捷键
Open editor from the settings:在 PowerToys 设置中打开"窗口管理器 → 自定义布局"进入编辑器;Open editor with a shortcut:通过快捷键(默认Win + Ctrl + \)呼出编辑器。
这两条在自动化中统一收敛为"以带参数方式启动编辑器进程并验证主窗口出现"。典型实现见 RunFancyZonesEditorTest.cs 与 FirstLunchTest.cs:测试在TestInitialize中先写入editor-parameters.json、六类模板、空的自定义/默认/快捷键/已应用布局数据,再调用RestartScopeExe()重启编辑器作用域,随后用Session.Find断言主窗口(AccessibilityId.MainWindow = "MainWindow1")存在。
3.2 布局生命周期:新建、复制与删除
清单中的布局 CRUD 用例集中在几个测试类中:
| 清单条目 | 自动化落点 |
|---|---|
| Create a new layout (grid and canvas) | CreateLayoutTests.cs 中的CreateGrid、CreateCanvas、CreateWithCustomName,以及取消路径CancelGridCreation、CancelCanvasCreation |
| Duplicate a template and a custom layout | CopyLayoutTests.cs,覆盖模板在编辑窗口内复制(CopyTemplate_FromEditLayoutWindow)、复制后成为默认布局(CopyTemplate_DefaultLayout),自定义布局经编辑窗口(CopyCustomLayout_FromEditLayoutWindow)、右键菜单(CopyCustomLayout_FromContextMenu)、默认布局(CopyCustomLayout_DefaultLayout)与保留快捷键(CopyCustomLayout_Hotkey)等路径 |
| Delete layout | DeleteLayoutTests.cs,覆盖删除未应用布局、删除已应用布局、取消删除、右键菜单删除、删除默认布局与删除后释放快捷键 |
其中"复制"操作有两种 UI 形态:在Templates(模板)分区点击Create custom layout,或在Custom(自定义)分区使用Duplicate。测试代码中这两种形态分别通过编辑窗口内的复制按钮(AccessibilityId.CopyTemplate/DuplicateLayoutButton)和右键上下文菜单实现,最终断言的共同点是"新布局确实存在、数据正确"。
3.3 布局编辑:模板参数、画布分区与网格结构
- 编辑模板(分区数、间距、高亮灵敏度)并验证重启后设置保持不变:对应 TemplateLayoutsTests.cs 中的
ZoneNumber_Cancel、HighlightDistance_Initialize/Save/Cancel、SpaceAroundZones_*一组用例。由于模板参数同样写入layout-templates.json,"重开编辑器后设置不变"正是通过"改参数 → Save → 重启编辑器 → 回读界面状态"来断言的。 - 编辑画布布局(分区大小与位置、新建/删除分区):对应 EditLayoutTests.cs 中
Canvas_AddZone_Save/Cancel、Canvas_DeleteZone_Save/Cancel、Canvas_MoveZone_Save/Cancel、Canvas_ResizeZone_Save/Cancel。画布编辑窗口的类名为Canvas layout editor(见 FancyZonesEditorHelper.cs 中的ElementName常量),分区控件类名为CanvasZone,新增分区按钮AccessibilityId.NewZoneButton。 - 编辑网格布局(拆分、合并、缩放分区):对应同一文件中的
Grid_SplitZone_Save/Cancel、Grid_MergeZones_Save/Cancel、Grid_MoveSplitter_Save/Cancel。网格编辑窗口类名为Grid layout editor,合并操作经由Merge zones按钮完成。
值得注意:上述几乎每个编辑动作都同时存在Save 与 Cancel 两种收尾,这正对应清单中的专门条目Check Save and apply and Cancel buttons behavior after editing——UI 测试用"取消后回读断言编辑未生效、保存后断言数据已写入"的方式把"事务性"语义固化为回归保障。
3.4 显示器分配、默认布局与切换快捷键
Assign a layout to each monitor:为每台显示器分别指定布局。对应 RunFancyZonesEditorTest.cs 的ClickMonitor(验证显示器卡片可切换选中态),以及 ApplyLayoutTests.cs 的ApplyLayoutsOnEachMonitor。Assign keys to quickly switch layouts (custom layouts only), Win + Ctrl + Alt + number:仅自定义布局可绑定切换快捷键。对应 LayoutHotkeysTests.cs 的HotKey_Assign_Save、HotKey_Assign_Cancel、HotKey_Assign_AllPossibleValues。Assign horizontal and vertical default layouts:设置横向/纵向显示器的默认布局。对应 DefaultLayoutsTest.cs 的Default_Assign_Save、Default_Assign_Cancel。该用例会在每个布局的编辑窗口中点击SetLayoutAsHorizontalDefaultButton/SetLayoutAsVerticalDefaultButton,再以 Save/Cancel 两个分支分别断言默认布局是否被改写,并会用Default_Initialize校验预置数据(横向默认 Grid、纵向默认某自定义布局)在编辑器界面上的勾选状态。
3.5 右键"复制焦点"行为
清单第一部分的最后一条专门描述了一个交互细节:在 Templates/Custom 区域左键选中布局 X,再右键布局 Y 并执行复制,期望结果是Y 被复制(而非当前选中的 X)——即复制动作的焦点是右键点击的对象。这在 UI 自动化中对应"右键点击 → 弹出ContextMenu→ 点击菜单项"的标准链路(helper 中封装的ClickContextMenuItem),并在CopyLayoutTests/OpenEditLayoutDialog_ByContextMenu_*等用例中以右键方式触发复制与编辑来持续守护该行为。
四、第二部分:补充 UI 测试场景的增量要点
清单第二部分没有沿用"手工用例"的叙事,而是直接按可自动化的场景枚举了更细的断言点,这些场景多数已经在上述测试类中落地,理解它们能帮你把握 UI 测试工程的覆盖边界。
4.1 前置数据注入与 UI 初始状态
- Add test data and start → verify data is correct (custom layouts, template layouts, defaults, shortcut keys):这是所有测试类的共同模式——先在
TestInitialize中用序列化器把预置数据写入对应 json(自定义布局、六类模板、横向/纵向默认布局、快捷键),再启动编辑器,最后逐项核对界面。 - UI Init: assigned layouts selected / applied default / assigned custom layout but id not found:用于验证编辑器启动后,已分配布局与默认布局能正确回显;当
applied-layouts.json引用了已不存在的自定义布局 UUID(用户删除了该布局但分配记录仍在)时,编辑器不应崩溃,UI 状态应合理。此类"脏数据兼容"逻辑集中在 UIInitializeTest.cs 中。
4.2 新建与复制的完整断言闭环
清单为"新建/复制"单列出带校验的条目:创建画布/网格后要"verify the layout exists",取消后要"doesn't exist";复制模板/自定义布局后还要额外检查副本是否继承了快捷键与默认布局身份。对应到测试就是每个动作的 Save 分支断言数据文件或界面中新增了实体、Cancel 分支断言无残留。
4.3 删除的副作用语义
删除类补充场景在 DeleteLayoutTests.cs 中被自动化得相当完整:
- 删除未应用布局(不影响任何显示器);
- 删除已应用布局(验证
applied-layouts.json中的分配随之失效); - 取消删除(布局保留);
- 从上下文菜单删除;
- 删除绑定了快捷键的布局 → 快捷键应被释放(
Delete: hotkey released,即DeleteLayoutWithHotkey); - 删除被设为默认布局的布局 → 默认布局应回退到系统默认(
Delete: default layout reset to default-default,即DeleteDefaultLayout)。
4.4 编辑器启动时 UI 参数回显
- Assign the same template but with different params to monitors:同一模板(如 Grid)在不同显示器上应用不同分区数/间距/灵敏度参数,需要保证按显示器分别持久化,对应 ApplyLayoutTests.cs 的
ApplyTemplateWithDifferentParametersOnEachMonitor。 - Assign layout on each monitor / Assign custom / Assign template:覆盖分配操作的类型分支,落在
ApplyLayoutTests与RunFancyZonesEditorTest。
4.5 快捷键与默认布局的保存/取消
Assign shortcut key and save/cancel、Reset shortcut key and save/cancel:对应LayoutHotkeysTests的HotKey_Assign_Save/Cancel与HotKey_Reset_Save/Cancel——新增Win + Ctrl + Alt + 数字绑定或重置绑定后,分别验证保存生效与取消还原;Set default layout + verify both prev and current after reopening:先记录原默认布局,设置新默认并保存,重启编辑器后同时验证"原默认已解除、新默认已生效",对应DefaultLayoutsTest。
4.6 持久化兼容与首次启动
- applied-layouts.json keeps info about not connected devices / other virtual desktops:显示器被拔出或切到其他虚拟桌面后,编辑器不应丢失这些显示器/桌面已有的布局分配——即
applied-layouts.json要能保存并恢复与当前未连接设备相关的记录。 - first launch without custom-layouts.json / default-layouts.json / layout-hotkeys.json / layout-templates.json:全新机器上这些文件尚不存在时,编辑器首次启动必须正常渲染出默认模板集并可用。这正是 FirstLunchTest.cs 中
FirstLaunch用例的验证目标——测试将各文件预置为合法空集合后重启编辑器,断言主窗口正常出现。
五、驱动这些用例的测试基础设施
5.1 框架与驱动链
FancyZonesEditor.UITests是基于MSTest(Microsoft.VisualStudio.TestTools.UnitTesting)的 Windows UI 测试工程(FancyZonesEditor.UITests.csproj),驱动链为:
MSTest 测试方法 └─ Microsoft.PowerToys.UITest(Session / UITestBase 封装) └─ OpenQA.Selenium.Appium.Windows(Appium Windows Driver 客户端) └─ Windows Application Driver (WinAppDriver) └─ 目标:FancyZones 编辑器 WPF 进程Init.cs 中的[AssemblyInitialize]会在整个程序集测试启动前拉起C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe,[AssemblyCleanup]在结束后将其关闭——这意味着本机运行前必须安装 WinAppDriver 与已构建的 PowerToys。
5.2 UI 元素定位:用 AccessibilityId 对抗界面变更
由于编辑器为 WPF 应用,测试统一通过AutomationId / 名称 / 控件类型定位元素,所有关键 ID 集中在 FancyZonesEditorHelper.cs 的三个静态类里,这也是把清单条目稳定翻译成自动化脚本的"契约层":
AccessibilityId:主窗口MainWindow1、新建布局按钮NewLayoutButton、编辑按钮EditLayoutButton、画布/网格单选框CanvasLayoutRadioButton/GridLayoutRadioButton、间距滑杆Spacing、灵敏度滑杆SensitivityInput、快捷键下拉框quickKeySelectionComboBox、横向/纵向默认按钮、删除/复制按钮等;ElementName:Save/Cancel、右键菜单项Edit/Edit zones/Delete/Duplicate/Create custom layout、画布与网格编辑窗口标题、Merge zones按钮;ClassName:ContextMenu、TextBox、Popup、CanvasZone、GridZone、Thumb等 Win32/WPF 类名。
右键场景通过element.Click(true)(模拟右键)弹出上下文菜单,再在ContextMenu内按菜单项文本定位点击——这与 3.5 节描述的"复制焦点"行为天然对应。
5.3 测试数据文件的写入与还原
每个测试类在TestInitialize阶段做四件事:FancyZonesEditorHelper.Files.Restore()还原全部数据文件 → 构造内存中的EditorParameters/LayoutTemplates/CustomLayouts/DefaultLayouts/LayoutHotkeys/AppliedLayouts对象 → 用各自的Serialize方法写入对应 json →RestartScopeExe()重启编辑器。断言阶段则"反向"回读文件或界面状态,例如DefaultLayoutsTest会在每个模板/自定义布局的编辑窗口中检查默认布局按钮的 Checked/Unchecked 态,并用Cancel逐个关闭对话框。
这种做法使得同一个测试类既能验证 UI 交互,又能验证 json 持久化结果——清单中所有涉及"重开编辑器后保持/重置""取消不生效"的条目,本质上都依赖这套可重复注入、可精确还原的数据夹具机制。
六、运行环境与本地执行前提
要在本机复跑这份清单对应的 UI 测试,需要满足:
- Windows 系统:FancyZones 与 WinAppDriver 均为 Windows 专属;
- 已构建并安装的 PowerToys(含 FancyZones 模块),路径与启动器约定保持一致;
- 安装Windows Application Driver(默认路径
C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe,见Init.cs); - 在 Visual Studio 的 Test Explorer 中打开含 FancyZonesEditor.UITests.csproj 的筛选解决方案并运行测试,或用
vstest.console.exe/dotnet test指向已构建的测试程序集。
由于测试会真实拉起编辑器窗口并模拟点击,运行期间请勿占用鼠标/键盘。清单中用例在迁移完成后即成为 CI 与 Release pipeline 的一部分,与发布流程(参考 release-process.md)配合,替代发布前的人工点检。PowerToys UI 测试的通用工程约定还可参考 ui-tests.md。
七、迁移进度的跟踪方式与工程参考
作为跟踪清单,release-test-checklist.md中的- [ ]状态即代表"该场景尚未/已经完成自动化"。推进迁移的推荐做法与仓库现状高度一致:先把清单条目按功能归类,逐类阅读对应的测试类确认覆盖情况;尚未覆盖的条目再补齐到对应的测试类中。从工程现状看,清单第一部分几乎全部条目都已能在FancyZonesEditor.UITests中找到对应实现(详见第三、四节的映射),第二部分的多数据文件持久化与首次启动用例也已由FirstLunchTest、DefaultLayoutsTest、LayoutHotkeysTests等承载。
若想深入某类布局的编辑逻辑或数据序列化细节,可继续研读:
- 测试主体:FancyZonesEditor.UITests 目录下的
RunFancyZonesEditorTest.cs、CreateLayoutTests.cs、CopyLayoutTests.cs、DeleteLayoutTests.cs、EditLayoutTests.cs、TemplateLayoutsTests.cs、ApplyLayoutTests.cs、LayoutHotkeysTests.cs、DefaultLayoutsTest.cs、UIInitializeTest.cs; - 数据模型与路径:FancyZonesEditorCommon/Data 下的
FancyZonesPaths.cs、EditorParameters.cs、LayoutTemplates.cs、CustomLayouts.cs、DefaultLayouts.cs、LayoutHotkeys.cs、AppliedLayouts.cs、Constants.cs; - 测试辅助:Utils/FancyZonesEditorHelper.cs、Utils/FancyZonesEditorFiles.cs、Utils/IOTestHelper.cs;
- 功能背景:doc/devdocs/modules/fancyzones.md 与 FancyZones 模块源码 src/modules/fancyzones/FancyZones。
总而言之,这份清单的价值不在于"列出要点的表格",而在于它把 FancyZones 编辑器最容易被回归遗漏的行为——取消语义、默认回退、快捷键释放、脏数据兼容、断连显示器持久化、无配置文件首启——逐条固化成了可执行、可断言的 UI 自动化资产。理解清单与测试源码的对应关系,你既能在发布前快速定位回归风险点,也能为编辑器后续的功能演进持续补充自动化防线。
【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考