
-
录制、重播和查看:使用 Xcode 实现 UI 自动化
了解如何在 Xcode 中录制、运行和维护 XCUIAutomation 测试。利用测试计划配置,在数十个语言、设备类型和系统条件下重播 XCTest UI 测试。使用 Xcode 测试报告来查看测试结果,并下载运行情况的截图和视频。我们还将介绍有关通过辅助功能为 App 做好自动化准备以及编写稳定、高质量自动化代码的最佳做法。
章节
- 0:00 - 简介与内容安排
- 3:58 - UI 自动化概览
- 6:26 - 为 App 做好自动化准备
- 11:32 - 录制交互操作
- 17:30 - 以多种配置重播
- 20:54 - 查看视频和效果
- 24:16 - 后续步骤
资源
- Delivering an exceptional accessibility experience
- Improving code assessment by organizing tests into test plans
- Performing accessibility testing for your app
相关视频
WWDC24
WWDC23
WWDC22
WWDC21
-
搜索此视频…
大家好 我叫 Max是 Xcode 团队的工程师 Xcode 满载令人惊叹的功能和体验 可能会让人应接不暇 比如 你知不知道 只需点按一次便可观察你的 App 在数十台设备、 多种语言及不同配置下的运行状况? 除此之外 每次运行都能录下完整高清视频 借助 Xcode 的 UI 自动化功能这完全没问题 我们来看看具体怎么操作 首先 我们将简要介绍 UI 自动化 然后 我们将准备你的 App将交互记录为自动化代码 并在多台设备和多种语言环境下 回放这段自动化代码 最后 观看结果所对应的视频录像 并查看一份报告 看看每次运行是成功还是失败
我们首先简要介绍一下 UI 自动化的工作原理
Xcode 中有两个测试框架:Swift Testing 和 XCTest 两个框架都能以多种配置 快速测试你的 App 以及源代码
当你导入 XCTest 时 将自动包含一个名为XCUIAutomation 的框架 XCUIAutomation 可用于自动化你的 App 并像人一样与 App 交互 这些框架协同工作 共同构成了一套完整的 App 测试套件 要是问我的话 我会觉得这相当不错 完整的 App 测试套件通常包含单元测试 和 UI 自动化测试 单元测试用于测试 App 的逻辑和模型 借助 Swift Testing 可以对那些甚至没有用户界面的框架 和 Swift 软件包运行测试 而 UI 自动化测试用于验证App 的用户体验 以及它与 Apple 硬件的集成情况 和常见工作流程的行为
通常 测试套件里包含的单元测试将多于 UI 测试 且力求覆盖全部代码 而 UI 自动化测试能让你查看 App 的外观、 行为以及与操作系统其他部分的集成情况 进行这项测试有很多好处
例如 你可以像用户一样使用轻点、轻扫和点按 等手势来测试 App 你可以了解那些使用 “旁白”、“语音控制” 和“动态字体”等辅助技术的用户 对 App 的使用体验
你可以查看 App 在它支持的所有语言 和地区的运行情况 并重点关注对 App 外观影响较大的语言 例如字符串较长的语言以及采用从右向左布局的语言 你可以测试 App 与 Apple 硬件功能的集成情况 比如操作按钮、相机按钮、 Apple TV Remote 和 Apple Watch 的数码表冠 最后 可以测试 App 的启动性能 这是了解用户多快能上手使用 你的 App 的关键指标 要设置 UI 自动化工作流程有三个关键阶段: 录制、回放和检查
首先录制你的交互操作 比如轻点、轻扫以及硬件按钮按压操作 然后观看 Xcode 自动将 这些操作编写为代码 接下来 在多个设备配置、 多种语言环境、多个地区设置、 多个设备方向上回放你的交互 整个过程可以在你的设备上 和 Xcode Cloud 中完成 最后 查看有关 App 在所有这些配置下 运行状况的视频和结果看看哪些通过了 哪些失败了 所有 Apple 平台都支持UI 自动化:iOS、iPadOS macOS、watchOS、Apple tvOS和 visionOS (专为 iPad 设计) 同一自动化流程甚至 能在多个平台上运行 因此 构建一次自动化流程 并在所有受支持设备上运行是可行的 意味着可查看 App 在 Mac、iPhone和 Vision Pro 上的运行情况 只需点按一下 无需更改代码 让我们简要了解一下UI 自动化的工作原理 UI 自动化会像人那样通过手势和硬件事件 与你的 App 交互 自动化完全独立于你的 App 运行 因此 你无法直接访问App 模型和数据
UI 自动化会告知操作系统 要执行哪些手势 然后同步等待手势逐个完成
这些操作包括启动 App、与按钮和导航交互、 设置深色模式等系统状态、 甚至按需为设备设置模拟位置 无障碍使用是 Apple 的核心价值观之一 Apple 的辅助技术确保每个人都能使用你的 App 不论是不是存在身体、视觉、听觉或运动方面的障碍 我们竭尽全力确保 这些技术中的大多数 都能默认与你的 App 兼容 作为开发者 你无需做任何额外工作 话虽如此 添加额外支持可以丰富 App 的使用体验 还能让自动化测试变得更加容易 关键在于 辅助功能是 支撑 UI 自动化的底层框架 拥有出色的辅助功能体验 意味着也可以获得出色的 UI 自动化体验 辅助功能直接向UI 自动化提供信息 例如元素类型、标签、值和框架 但辅助功能“看到”的内容 未必和用户肉眼看到的一一对应 我们来看一个例子 在这个屏幕上的 UI 中可以看到 “Great Barrier Reef”按钮 而辅助功能能“看到”更多内容 当然 辅助功能可以“看到”元素类型和标签 将它们公开给 UI 自动化 但与此同时 标识符属性也会公开 辅助功能标识符可用于唯一地标识屏幕上的任何元素 这种标识是相对于这个元素 周围的所有其他元素而言的 这个标识符的设计没有考虑本地化 因此可用于在任何语言环境或设备中指代同一 UI 元素
对于复选框和其他有状态元素 可使用 value 属性 这会向辅助功能和 UI 自动化显示元素的当前状态
要进一步了解辅助功能 请观看 WWDC23 讲座“在 SwiftUI和 UIKit 中创建易于访问的 App” 或 WWDC21 讲座“SwiftUI辅助功能:超越基础功能”
我们已经探讨了 UI 自动化如何与辅助功能协作 下面我们开始准备 App 自动化
首先添加辅助功能标识符 随后快速检查 App 的辅助功能 最后将添加新的UI 测试目标 以准备好将我们的交换记录为代码 开始之前 需要注意的是 你的 App 已经内置了对UI 自动化和 UI 录制的全面支持 作为开发者 你无需做任何额外工作 我们将介绍的步骤并不是 必须完成的步骤 但可以带来更出色、更高质量的结果 在用 SwiftUI、UIKit 或 AppKit 编写的视图代码中 可添加辅助功能标识符 辅助功能标识符是自动化测试中唯一标识 App 内任何元素的最佳方式 最好为具有本地化字符串 或动态内容的元素 添加辅助功能标识符 这包括任何数据模型中的内容 或是从互联网下载的内容
理想的标识符在 整个 App 中应是唯一的 描述要足够清晰以详细说明 它们所关联的元素 并且是静态的 不会因内容的变化而改变
虽然标题和描述可能会改变但良好的标识符总是可以描述 它们所关联元素的内容 这样一来 就可以确保我心爱的地标一直存在
在 SwiftUI 中accessibilityIdentifier 修饰符 可添加到任何 UI 元素 只要你的视图及父视图未对辅助功能隐藏 这个修饰符就会被识别
为视图实例创建特定的标识符 是个好主意 尤其是对于在 App 中多次使用的视图 在这个示例中 我们使用地标的 id 属性 让每个 ID 的标识符具有唯一性
在 UIKit 中accessibilityIdentifier 属性 可在任何 UIView 上设置只要视图是辅助功能元素即可 大多数 UI 视图 比如控件、文本和图像 默认是辅助功能元素 因此通常无需额外操作
像 accessibilityLabel、accessibilityTraits 和 accessibilityValue 等属性对于“旁白”等辅助技术非常有用 对 UI 自动化也很有用
但 accessibilityIdentifier 属性 不会被“旁白”朗读出来 也不会向使用你 App 的任何人公开 这使它成为一种有用的方式 可用于提供只对自动化有用的信息 例如表格单元格索引或图像的符号名称 我甚至能让 Xcode中的编程助理 帮我添加辅助功能标识符 例如 我可以输入 “为这个视图的相关部分添加辅助功能标识符” 随即便会添加相应的辅助功能标识符 编程助理甚至知道如何在地标上使用 id 属性 以便每个标识符完全具备唯一性 太酷了 在开始 UI 录制前最好先检查 App 的 整体辅助功能表现 这好比在去牙医那里之前先自己用牙线清理一遍牙齿 你很快就会清楚自己做得怎么样 这能让你提前了解概况 Xcode 自带一个名为Accessibility Inspector 的 App 让你能够查找、诊断和修复辅助功能问题 可以从”Xcode“顶层菜单的“Open Developer Tool”下 启动这个 Inspector 也可以从“聚焦”中启动它
Accessibility Inspector 可以列出你的 App 在任意平台上 任意视图的辅助功能值 只需选择要检测的平台 然后点按 Element 检查器并与这个平台上 你想要了解的 UI 元素交互 随即将显示元素属性列表 其中一些元素比如”Basic“部分中的元素 对于 UI 自动化非常有用 对于缺少信息的视图 可能需要更改 App 的源代码并加以补充 点按属性的名称可了解各个属性的详细信息 弹出窗口将明确指出要设置哪个属性 提供它的相关文档及更多内容
你可以通过我们的示例代码项目“提供出色的辅助功能体验” 了解辅助功能的更多信息 这个项目为使用许多辅助功能的 App 提供了一些很棒的代码示例 并且对 UI 自动化非常友好 你也可以查阅文章 “为你的 App 执行辅助功能审核” 以了解借助各类不同辅助技术 检查 App 辅助功能的方法 准备好开始自动化后需要添加新的 UI 测试目标 以便指定地点来存放自动化代码
在 Xcode 的项目设置视图中 轻点目标列表下方的“加号”按钮添加新目标
然后 从弹出窗口中选择“UI Testing Bundle”
点按“Finish”后新的 UI 测试文件夹和模板 将添加到你的项目中 这个模板包含一些简单测试来帮助你入门 好了 我们已准备好像变魔术一样将所有交互都记录为 Swift 代码 我们将使用 iOS 模拟器和 Xcode 完成这项操作 几年前 我的妈妈和姐姐 去澳大利亚旅行了一个月没带上我 我很郁闷没能和她们一同前去 幸好 有款 App 能帮助我实现心愿 我可以使用来自今年 WWDC的 Landmarks 示例项目 规划我自己的假期 我会记录一些用于规划行程的交互 这样能确保相应工作流程在 App 后续版本中 不会出问题 首次打开 UI 测试源文件时 将出现一个弹出窗口告诉我如何开始 UI 录制 现在 我使用边栏的这个按钮开始 UI 录制 Xcode 将在模拟器中自动构建并重新启动我的 App
现在我的 App 已经启动 我将进入集合视图
在我与 App 交互时 代表交互的代码会记录在源代码编辑器中 我将轻点加号按钮添加新集合 以便开始规划我自己的澳大利亚之旅 现在我将轻点“Edit”按钮来重命名这次旅行 我可以将这次旅行重命名为“Max’s Australian Adventure”
在我输入文本时 Xcode 会实时更新测试内容
现在 我将编辑地标集合
只需添加一些澳大利亚地标比如“Great Barrier Reef” 还有“Uluru” 然后轻点勾号
回到集合视图后 能看到我的集合已添加成功 添加了一些澳大利亚地标
可以点按 Xcode 中的“Stop Run”按钮停止 UI 录制 录制完成后 你可能需要完成几个步骤 确保得到想要的自动化流程 首先 检查录制的代码 然后 使用 XCTest API 添加验证 确保 App 按预期运行 最后 探索其他自动化 API 它们能让你的测试功能更强大
我们来检查一下记录的 UI 查询 看看是不是需要做出调整 已记录的每一行代码都会针对每个 UI 元素提供多个选项 具体选择哪一个取决于你的目标 可点按每一行源代码上的下拉菜单来查看相应选项
小提示 选对选项 将帮你更快地登上飞往澳大利亚的飞机
我们有一些建议可以帮助你从这些选项中进行选择
对于具有文本元素或按钮等本地化字符串的视图 如果存在辅助功能标识符建议选择它 如果存在标识符UI 记录默认会尝试使用它
对于深度嵌套的视图比如滚动视图中的文本 我们建议选择尽可能短的查询 这将有助于你的自动化流程在App 出现变化时依然保持稳定可靠
最后 对于从互联网下载的动态内容 或频繁变化的内容比如时间戳或温度 我们建议使用更通用的查询 如果存在辅助功能标识符 则建议使用它
这个示例中甚至没有使用标识符 或任何字符串只是单纯地引用第一段文本
好了 该做出选择了 我将点按要编辑的源代码行以查看选项 所有这些查询都能唯一标识你交互过的元素 因此无论怎么选都不会错 只是选择你想要如何存储对这部分 UI 的引用 供未来使用 我选择“textFields.firstMatch”选项 以确保在我的测试中无论文本字段的名称是什么 它总是会被轻点 连按任一下拉菜单将这个结果存储到源代码中 现在快速重新运行我的自动化 看看是否正确录制了我的操作 点按菱形测试图标来运行 虽然正在测试你的 App 但我们并非要考验你的耐心 自动化回放运行得非常快
系统会使用正确名称快速创建集合 随即添加位置
自动化测试已经通过 太棒了 这比 19 小时的航班要快得多 现在可以为代码添加验证功能 以检查预期行为 在这个示例中 我将验证 Great Barrier 地标是否已加入我的集合
我可以调用诸如 waitForExistence 这样的方法 让自动化等待某个元素出现然后再继续 我还可以调用更通用的方法wait(for:toEqual:) 来验证 XCUIElement 上的任何属性 是否符合预期结果
我可以将这两个方法与 XCTest中的 XCTAssert 语句搭配使用 如果这些方法返回 false则让测试失败
接下来 我将回到代码并快速为我的集合名称添加 waitForExistence 以确保它在后续运行中始终存在
现在是探索其他自动化 API 的好时机 让你的代码变得更强大
使用 XCTestCase 的setup 实例方法可能很有用 可确保设备在后续运行期间 保持相同的状态 可调用 orientation、appearance等 API 甚至可以模拟位置 以便设备在运行前进入正确状态
在启动 App 之前 我可以使用属性 比如 launchArguments和 launchEnvironment 让 App 在调用启动方法时使用这些参数
如果你的 App 支持自定 URL 方案 可使用 XCUIApplication 的 open 方法直接打开匹配的 URL
甚至还有一个全局版本 这个版本会用设备上默认打开 这类 URL 的 App 来打开它
最后 可在 UI 测试中对你的 App 执行辅助功能审核 有一个很棒的讲座名为“为你的 App 执行辅助功能审核” 这个讲座出自 WWDC23 现在已记录交互并已设置好自动化 接下来将配置测试以便在多种配置中回放 包括桌面端环境和云端环境 将测试加入新的或现有测试计划非常有用 测试计划让你能够包含或排除单个测试 针对测试的运行位置和方式 设定系统设置 以及管理测试属性如超时、重复次数 并行化设置、执行顺序等
测试计划还与方案相关联 方案让你可以将测试计划与特定的构建设置进行配对
你可阅读开发者文档中的 《通过将测试组织成测试计划来改进代码评估》 深入了解更多相关内容
在测试计划中 可在第一个屏幕上添加或移除测试 或切换到“Configurations”标签页 以更改测试的运行方式 我可以设置多个配置让 App 在多个语言环境下运行
通常 测试计划中的每个语言环境都作为一个独立的配置存在
你可以拥有针对特定语言环境配置而专门定制的设置 也可以拥有在所有语言环境配置中 共享的设置
包含针对字符串较长的 语言 (如德语) 或从右到左书写语言 (如阿拉伯语和希伯来语) 的配置 会很有帮助
“Configurations”标签页中 甚至有 UI 自动化专属设置
其中包括运行期间是否捕获视频或截屏 以及之后是否会保留任何媒体文件
默认情况下 视频和截屏仅在运行失败时予以保留 方便你检查任何问题 如果你想为所有运行保留它们(包括通过的运行) 请选择“On, and keep all” 这个设置可让你保留视频录像以用于其他目的 比如文档、教程或营销 “Configurations”标签页 中还有许多其他出色的设置可供探索 要进一步了解这些设置 请观看 WWDC22 的讲座“为 XcodeCloud 编写快速且可靠的测试”
Xcode Cloud 是 Xcode 内置的服务也可在 App Store Connect 中使用 它可以帮助你构建 App、运行测试、上传到 App Store 等等 所有操作都在云端执行 无需使用你或团队的任何设备 我想你会发现Xcode Cloud 使用起来轻松愉快 对于“Landmarks”App 我们配置了一个 Xcode Cloud 工作流程 它运行我刚刚编写的所有 UI 自动化功能 依据的是我刚刚创建的测试计划 这个计划在云端的运行方式与在模拟器上是一样的 可在任意数量的设备(包括 iPhone 和 iPad) 上运行 并支持英语、阿拉伯语、希伯来语和德语等多种配置
你可以在 Xcode 中查看Xcode Cloud 运行的历史记录 或在 App Store Connect 的“Xcode Cloud”部分中查看 在那里你能概览构建信息、日志 失败描述等内容
使用 Xcode Cloud 我的整个团队都可以看到我的运行历史记录 并从中下载结果和视频录像 即便我真的身处云端他们也能这么做 我是说当我身处飞往悉尼的航班上时
关于 Xcode Cloud 还有很多内容等待我们去探索 如需了解更高级配置 请观看 WWDC23 讲座“在 XcodeCloud 中创建实用的工作流程” 现在 我们已用测试计划在多种配置下运行了记录的测试 可通过测试报告查看结果和视频录像 Xcode 测试报告提供了一些绝佳工具可帮助你查看、了解 并诊断测试结果 似乎在我刚刚运行的自动化测试中有一次测试运行失败了 看来我还不能收拾行囊去澳大利亚 为了定位失败的测试我将点按“Test”按钮 然后连按失败的运行 以通过查看视频录像和描述来了解究竟发生了什么情况
我可以在运行下拉菜单中看到这个测试中的所有运行记录 这样我就能在不同配置 (比如不同语言) 下 运行的测试所对应的视频录像 之间进行快速切换 另外 有趣的是 我还能下载视频 方法是辅助点按并选择“Save”
我将按下播放按钮来开始视频回放
视频播放时 显示 UI 交互的圆点会叠加在视频上方 这些操作也会在下方时间轴以圆点显示
看起来距离我失败之前还有一段时间 快进一下 通过时间轴上的失败菱形图标可直接定位到失败的时刻
我看到一条失败信息但难以确定哪里出错 信息显示我们在寻找一个按钮 名为“Max's AustralianAdventure” 看看失败时实际上显示了什么内容
在失败瞬间 我看到有个叠层 显示了当时存在的所有 UI 元素 就在视频录像的顶部
如果我点按其中任意一个 就会得到有关如何在自动化代码中 处理这个元素的代码建议 我甚至可以点按“Show All”以查看其他示例 并找到适合我的示例 我想我知道问题出在哪里了 我们当时期望有一个按钮 但这里没有 实际上只有文本 我要快速修复一下
选中我需要的示例并辅助点按以拷贝它
接着可以点按“View Source”以便直接前往我的测试 并粘贴新的代码行来替换原有代码行
现在 可以将临时的XCUIApplication 变量 替换为用于 UI 录制的 App 变量然后就可以了
很好 现在应该会按预期运行了 我来点按菱形测试图标观看测试重新运行 这一次 我将用阿拉伯语运行测试看看在 App 以从右至左的布局方式 运行时同一自动化流程是否仍可以正常执行
自动化会快速创建我的集合 并像在英文环境中一样对它重命名 太棒了
看来自动化测试通过了 是时候完成这件事 然后开启难忘的旅程了 也许我的妈妈和姐姐能陪我一起逛逛 借助 Xcode 测试报告我们可以实现更多操作 幸运的是 WWDC23 讲座“使用 Xcode 测试报告更快修复故障” 深入讲解并涵盖了所有相关内容 令人惊叹的地方在于UI 自动化、辅助功能 本地化、Xcode Cloud 和测试报告 一起协同工作 共同提高 App 的质量 让全球所有用户都能更轻松地使用 将这些技术整合到一个流程中真是 一件令人愉悦的事 我迫不及待地想看看开发者会如何使用它了
要进一步了解单元测试和 Swift Testing 可以观看 WWDC24 的“了解 Swift Testing”讲座 如果有其他问题或反馈 可以在开发者论坛中联系我们 感谢你的观看 我们澳大利亚见
-
-
7:52 - Adding accessibility identifiers in SwiftUI
// Adding accessibility identifiers in SwiftUI import SwiftUI struct LandmarkDetailView: View { let landmark: Landmark var body: some View { VStack { Image(landmark.backgroundImageName) .accessibilityIdentifier("LandmarkImage-\(landmark.id)") Text(landmark.description) .accessibilityIdentifier("LandmarkDescription-\(landmark.id)") } } }
-
8:19 - Adding accessibility identifiers in UIKit
// Adding accessibility identifiers in UIKit import UIKit struct LandmarksListViewController: UIViewController { let landmarks: [Landmark] = [landmarkGreatBarrier, landmarkCairo] override func viewDidLoad() { super.viewDidLoad() for landmark in landmarks { let button = UIButton(type: .custom) setupButtonView() button.accessibilityIdentifier = "LandmarkButton-\(landmark.id)" view.addSubview(button) } } }
-
13:54 - Best practice: Prefer accessibility identifiers over localized strings
// Example SwiftUI view struct CollectionDetailDisplayView: View { var body: some View { ScrollView { Text(collection.name) .font(.caption) .accessibilityIdentifier("Collection-\(collection.id)") } } } // Example of a worse XCUIElementQuery XCUIApplication().staticTexts["Max's Australian Adventure"] // Example of a better XCUIElementQuery XCUIApplication().staticTexts["Collection-1"]
-
14:09 - Best practice: Keep queries as concise as possible
// Example SwiftUI view struct CollectionDetailDisplayView: View { var body: some View { ScrollView { Text(collection.name) .font(.caption) .accessibilityIdentifier("Collection-\(collection.id)") } } } // Example of a worse XCUIElementQuery XCUIApplication().scrollViews.staticTexts["Collection-1"] // Example of a better XCUIElementQuery XCUIApplication().staticTexts["Collection-1"]
-
14:21 - Best practice: Prefer generic queries for dynamic content
// Example SwiftUI view struct CollectionDetailDisplayView: View { var body: some View { ScrollView { Text(collection.name) .font(.caption) .accessibilityIdentifier("Collection-\(collection.id)") } } } // Example of a worse XCUIElementQuery XCUIApplication().staticTexts["Max's Australian Adventure"] // Example of a better XCUIElementQuery XCUIApplication().staticTexts.firstMatch
-
15:49 - Add validations to a test case
// Add validations to the test case import XCTest class LandmarksUITests: XCTestCase { func testGreatBarrierAddedToFavorites() { let app = XCUIApplication() app.launch() app.cells["Landmark-186"].tap() XCTAssertTrue( app.staticTexts["Landmark-186"].waitForExistence(timeout: 10.0)), "Great Barrier exists" ) let favoriteButton = app.buttons["Favorite"] favoriteButton.tap() XCTAssertTrue( favoriteButton.wait(for: \.value, toEqual: true, timeout: 10.0), "Great Barrier is a favorite" ) } }
-
16:36 - Set up your device for test execution
// Set up your device for test execution import XCTest import CoreLocation class LandmarksUITests: XCTestCase { override func setUp() { continueAfterFailure = false XCUIDevice.shared.orientation = .portrait XCUIDevice.shared.appearance = .light let simulatedLocation = CLLocation(latitude: 28.3114, longitude: -81.5535) XCUIDevice.shared.location = XCUILocation(location: simulatedLocation) } }
-
16:54 - Launch your app with environment variables and arguments
// Launch your app with environment variables and arguments import XCTest class LandmarksUITests: XCTestCase { func testLaunchWithDefaultCollection() { let app = XCUIApplication() app.launchArguments = ["ClearFavoritesOnLaunch"] app.launchEnvironment = ["DefaultCollectionName": "Australia 🐨 🐠"] app.launch() app.tabBars.buttons["Collections"].tap() XCTAssertTrue(app.buttons["Australia 🐨 🐠"].waitForExistence(timeout: 10.0)) } }
-
17:04 - Launch your app using custom URL schemes
// Launch your app using custom URL schemes import XCTest class LandmarksUITests: XCTestCase { func testOpenGreatBarrier() { let app = XCUIApplication() let customURL = URL(string: "landmarks://great-barrier")! app.open(customURL) XCTAssertTrue(app.wait(for: .runningForeground, timeout: 10.0)) XCTAssertTrue(app.staticTexts["Great Barrier Reef"].waitForExistence(timeout: 10.0)) } }
-
17:12 - Launch your app using custom URL schemes and the system default app
// Launch your app using custom URL schemes import XCTest class LandmarksUITests: XCTestCase { func testOpenGreatBarrier() { let app = XCUIApplication() let customURL = URL(string: "landmarks://great-barrier")! XCUIDevice.shared.system.open(customURL) XCTAssertTrue(app.wait(for: .runningForeground, timeout: 10.0)) XCTAssertTrue(app.staticTexts["Great Barrier Reef"].waitForExistence(timeout: 10.0)) } }
-
17:13 - Perform an accessibility audit during an automation
// Perform an accessibility audit during an automation import XCTest class LandmarksUITests: XCTestCase { func testPerformAccessibilityAudit() { let app = XCUIApplication() try app.performAccessibilityAudit() } }
-
-
- 0:00 - 简介与内容安排
Xcode 的 UI 自动化由 XCUIAutomation 框架提供支持,能够全面测试你的 App。它与 Swift Testing 和 XCTest 框架协同工作,提供完整的 App 测试套件。UI 自动化测试可验证 App 的用户体验、与 Apple 硬件的集成情况以及常见工作流程的行为,是对侧重于 App 逻辑和数据模型的单元测试的补充。 这个过程包括三个主要阶段: 录制交互,然后自动转换为代码。 在不同设备、语言、地区和屏幕方向中重播这些交互。 查看每次 UI 测试运行的视频录制和结果。 借助这些自动化功能,你能像真实用户一样测试 App,确保 App 的可访问性、语言支持和硬件集成。所有 Apple 平台都支持 UI 自动化,只需点按一下,即可为 iPhone、iPad、Mac、Apple TV 和 Apple Watch 等多种设备构建并运行一次自动化测试。
- 3:58 - UI 自动化概览
UI 自动化模拟用户与 App 的交互,包括启动 App、轻点按钮和浏览屏幕。它依赖于 App 的辅助功能 (这些功能为元素提供标签、值和唯一标识符) 来独立执行这些操作。辅助功能是 Apple 的一项核心价值观,它确保人人都能使用 App,同时也为 UI 自动化提供了支持。
- 6:26 - 为 App 做好自动化准备
准备 App 自动化涉及几个步骤。首先,将辅助功能标识符添加到 App 的元素中。这些标识符是用 SwiftUI、UIKit 或 AppKit 编写的唯一标签,可帮助自动化工具识别 App 的特定部分并与之交互。它们对于包含本地化字符串或动态内容的元素尤其有用,并且需要是描述性的、静态的,并且在整个 App 中是唯一的。 接下来,使用 Accessibility Inspector 快速查看 App 的辅助功能。这个工具可帮助识别和修复任何辅助功能问题,确保 App 为自动化做好充分准备。通过 Accessibility Inspector,你可以查看和修改每个视图的辅助功能属性,使 App 更易于用于辅助技术和自动化脚本。 最后,向 Xcode 项目添加新的 UI 测试目标。这个目标提供用于存储自动化代码的专用空间。设置目标后,你可以开始录制与 App 的交互,这些交互将自动转换为 Swift 代码,从而简化自动化过程。
- 11:32 - 录制交互操作
Xcode 和模拟器中显示的“Landmarks”示例项目演示了如果规划前往澳大利亚的虚拟假期。UI 录制将 App 内的交互操作以代码形式捕获。这个示例添加了一个新的集合,重命名为“Max's Australian Adventure”,并使用大堡礁和乌鲁鲁等地标填充这个集合。 录制停止后,这个示例将检查生成的代码,选择适当的 UI 查询,并使用 XCTest 添加验证以确保 App 的功能。然后重新运行测试,成功验证集合的创建和地标添加。你可以通过设置特定的设备状态、模拟位置和执行辅助功能审核来进一步增强测试。
- 17:30 - 以多种配置重播
Xcode Cloud 支持在桌面和云端以各种配置自动测试 App,并支持针对不同的语言和设备进行自动 App 测试。测试计划可以组织测试、设置系统设置和管理属性。配置允许在特定语言区进行测试,包括使用较长字符串或从右到左书写的语言。 Xcode Cloud 会在云中运行测试,并保存测试失败的视频和截屏以供查看。整个团队都可以查看运行历史记录、日志和结果,从而促进协作和远程监控。开发者文档中提供了高级配置和更多详细信息。
- 20:54 - 查看视频和效果
Xcode 测试报告提供了一个全面的工具来分析测试结果。在识别到失败的测试运行后,你可以访问视频录制和详细的说明。测试报告在视频上叠加 UI 交互,并提供一个带有失败菱形图标的时间轴,以便快速导航。 你可以查看故障点的当前 UI 元素、接收代码建议,并直接编辑测试代码。进行更正后,可以重新运行测试,测试报告还允许你验证不同语言和布局的功能,最终提升 App 的质量和可访问性。
- 24:16 - 后续步骤
要了解更多有关单元测试和 Swift Testing 的信息,请观看 WWDC24 讲座“了解 Swift Testing”;如有疑问或需要提供反馈,请访问开发者论坛。