.NET MAUI UI 测试如何用 VerifyScreenshot 建立截图基线并查看 CI 对比结果?
2026/9/14 13:28:20 网站建设 项目流程

.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.TapApp.WaitForElement)只能验证元素行为,无法验证页面渲染结果。VerifyScreenshot()是测试基类_IssuesUITest提供的方法,用于对当前页面做截图并和仓库中的基线截图做自动对比。本文基于docs/UITesting-Guide.mddocs/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_HOMEJAVA_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 测试由两部分组成,缺一不可:

  1. HostApp 页面:src/Controls/tests/TestCases.HostApp/Issues/IssueXXXXX.xaml(每个可交互元素必须设置AutomationId);
  2. 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],选择与主要控件对应的类别(ButtonLabelNavigation等,完整列表见 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 的步骤:

  1. 带着你的测试提交 PR;

  2. 等待 CI 运行完成;

  3. 在 PR 底部的 checks 区域找到Maui-UITestpublic(标记为 required),点击Details

  4. 点击 "View More Details on Azure Pipelines":

  5. 在摘要页找到 "Related" 区域,点击Consumed进入产物列表:

  6. 点击 "Drop" 旁边的三个点,下载产物:

第三步:把基线截图提交到仓库

下载并解压产物后:

  1. 进入Controls.TestCases.Shared/文件夹,找到你测试的快照(.png);
  2. 按平台放入对应的 snapshots 目录:
    • Androidsrc/Controls/tests/TestCases.Android.Tests/snapshots/
    • iOSsrc/Controls/tests/TestCases.iOS.Tests/snapshots/ios/
    • Windowssrc/Controls/tests/TestCases.Windows.Tests/snapshots/
    • MacCatalystsrc/Controls/tests/TestCases.Mac.Tests/snapshots/
  3. 文件名必须与测试方法名完全一致(例如测试方法TestMethodName对应TestMethodName.png);
  4. iOS 目录下存在ios/ios-iphonex/两个子文件夹,只提交到ios/
  5. Commit 并 push 到 PR。

仓库中已有对应目录可参考,例如 TestCases.Android.Tests/snapshots 下的androidandroid-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(); } #endif
  • Windows 上布局容器没有 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询