.NET MAUI UI 测试如何用 VerifyScreenshot 建立截图基线并查看 CI 对比结果?
【免费下载链接】maui.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.项目地址: https://gitcode.com/GitHub_Trending/ma/maui
在 .NET MAUI 仓库中做 UI 自动化测试时,交互断言(App.Tap、App.WaitForElement)只能验证元素行为,无法验证页面渲染结果。VerifyScreenshot()是测试基类_IssuesUITest提供的方法,用于对当前页面做截图并和仓库中的基线截图做自动对比。本文基于docs/UITesting-Guide.md与docs/design/UITesting-Architecture.md,走通一条完整路径:在测试中调用VerifyScreenshot()→ 让 CI 生成基线截图 → 把基线提交到仓库 → 后续 CI 中查看对比失败结果。
适用前提:你在maui仓库内为某个 Issue 编写 NUnit UI 测试,测试目标平台为 Android、iOS 或 Windows(VerifyScreenshot()目前不支持 MacCatalyst,见文末限制)。
准备工作:测试环境与测试的两段式结构
环境准备
按 UITesting-Guide.md 的要求,所有 UI 测试都基于Appium.WebDriver@8.0.1,本地运行测试前需要:
# Restore tools (required) dotnet tool restore # Install Node.js LTS from https://nodejs.org # Provision Appium dotnet build ./src/Provisioning/Provisioning.csproj -t:ProvisionAppium -p:SkipAppiumDoctor="true"各平台还有额外要求(见 UITesting-Guide.md):
- Android:设置
ANDROID_HOME和JAVA_HOME,安装 Android API 30 SDK 及 x86/x64 模拟器镜像; - iOS/MacCatalyst:需要 macOS、Xcode 及命令行工具、已配置 iOS 模拟器;
- Windows:开启开发者模式,安装 Windows App Driver v1.2.1,并把
%USERPROFILE%\AppData\Roaming\npm加入 PATH。
测试的两段式结构
仓库要求每个 UI 测试由两部分组成,缺一不可:
- HostApp 页面:
src/Controls/tests/TestCases.HostApp/Issues/IssueXXXXX.xaml(每个可交互元素必须设置AutomationId); - NUnit 测试:
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/IssueXXXXX.cs。
第一步:在测试中调用 VerifyScreenshot()
VerifyScreenshot()应放在测试末尾,此时页面处于你要校验的视觉状态:
using NUnit.Framework; using UITest.Appium; using UITest.Core; namespace Microsoft.Maui.TestCases.Tests.Issues; public class IssueXXXXX : _IssuesUITest { public IssueXXXXX(TestDevice device) : base(device) { } public override string Issue => "描述该 Issue 验证的问题"; [Test] [Category(UITestCategories.Button)] // 每个测试方法只允许一个 Category public void TestMethodName() { App.WaitForElement("ClickButton"); App.Tap("ClickButton"); App.WaitForElement("ResultLabel"); VerifyScreenshot(); // 测试末尾调用,截图并与基线对比 } }几个文档明确强调的写法约束:
- 交互前先
App.WaitForElement(...),不要直接App.Tap(...); - 每个测试方法只允许一个
[Category],选择与主要控件对应的类别(Button、Label、Navigation等,完整列表见 UITesting-Guide.md); - 如果测试需要特定方向,用
[SetUp]里调用App.SetOrientationPortrait()固定。
可选的本地快速调试:如果不想每次走测试选择界面,可以创建未被 git 跟踪的src/Controls/tests/TestCases.HostApp/MauiProgram.user.cs,通过OverrideMainPage(ref Page mainPage)直接把mainPage设为你的 Issue 页面,HostApp 启动后直达该页面,便于反复确认视觉效果(见 UITesting-Architecture.md)。
第二步:在 CI 上运行以生成基线
仓库没有提供"本地一键生成基线"的命令,基线截图来自 CI 产物。按 UITesting-Architecture.md 的步骤:
带着你的测试提交 PR;
等待 CI 运行完成;
在 PR 底部的 checks 区域找到
Maui-UITestpublic(标记为 required),点击Details:点击 "View More Details on Azure Pipelines":
在摘要页找到 "Related" 区域,点击Consumed进入产物列表:
点击 "Drop" 旁边的三个点,下载产物:
第三步:把基线截图提交到仓库
下载并解压产物后:
- 进入
Controls.TestCases.Shared/文件夹,找到你测试的快照(.png); - 按平台放入对应的 snapshots 目录:
- Android:
src/Controls/tests/TestCases.Android.Tests/snapshots/ - iOS:
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ - Windows:
src/Controls/tests/TestCases.Windows.Tests/snapshots/ - MacCatalyst:
src/Controls/tests/TestCases.Mac.Tests/snapshots/
- Android:
- 文件名必须与测试方法名完全一致(例如测试方法
TestMethodName对应TestMethodName.png); - iOS 目录下存在
ios/和ios-iphonex/两个子文件夹,只提交到ios/; - Commit 并 push 到 PR。
仓库中已有对应目录可参考,例如 TestCases.Android.Tests/snapshots 下的android、android-notch-36子目录,以及 TestCases.Mac.Tests/snapshots 下的mac子目录。
第四步:在 CI 中查看对比结果
基线入库后,每次 CI 运行时VerifyScreenshot()都会把当前截图与基线比对:
全部通过:测试正常结束,无快照差异产物;
对比失败:CI 会生成对比截图,失败截图带
-diff后缀,差异区域以红色高亮标出,可在 Azure Pipelines 的测试结果中查看:
CI 侧的实现逻辑在 ui-tests-collect-snapshot-diffs.yml:每个平台有一个检查步骤,检查$(Build.ArtifactStagingDirectory)/Controls.TestCases.Shared.Tests/snapshots-diff目录;目录内存在差异文件时,才发布名为uitest-snapshot-results-<platform>的管线产物。也就是说,只在"出现了截图差异"时你才会看到对应平台的 snapshot 产物,没有该产物本身说明该平台没有视觉回归。
限制与已知问题
MacCatalyst 暂不支持
VerifyScreenshot():需要在测试上使用前处理指令跳过,例如:#if !MACCATALYST [Test] public void ScreenshotTest() { VerifyScreenshot(); } #endifWindows 上布局容器没有 AutomationId:Appium 依赖 accessibility tree,Layout 在其上不可见;截图测试的页面交互应聚焦 Label、Entry、Button 等具体元素。
iOS 不支持嵌套可访问性元素:部分元素可能无法通过 accessibility tree 到达,文档给出的替代方式是扁平化 UI 层级或使用坐标点击(
App.TapCoordinates(100, 100))。若本地跑测试遇到问题,可用 UITesting-Guide.md 的排查方式,例如 Android 启动崩溃时用
adb logcat | grep -E "(FATAL|AndroidRuntime|Exception|Error|Crash)"查看完整异常。
本地运行单条测试(可选验证路径)
提交前先在本地至少一个平台跑通。以 Android 为例(来自 UITesting-Guide.md):
# 1. 部署 HostApp 到 Android 模拟器/设备 dotnet build src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj -f net10.0-android -t:Run # 2. 运行指定测试 dotnet test src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj --filter "FullyQualifiedName~IssueXXXXX"iOS、MacCatalyst 的对应命令以及按分类过滤(--test-filter="TestCategory=Button")的 Cake 用法,同样在该文档的 Running Tests 一节。
提交前按 UITesting-Guide.md 的 Pre-Commit Checklist 确认:两个项目无错误编译、XAML 的AutomationId与测试引用一致、命名符合 IssueXXXXX 约定、每个测试只有一个[Category]、至少一个平台本地通过、无编译警告。
【免费下载链接】maui.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.项目地址: https://gitcode.com/GitHub_Trending/ma/maui
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考