CI/CD 2026年9月1日 约 34 分钟 AppIntentsTesting App Intents

AppIntentsTesting 自动测试:2026 远程 Mac 部署指南

Shortcuts 手工验证通过,并不代表 App Intents 集成没有回归。本文从 Intent 执行、Entity Query、连续任务、Spotlight 和远程 Mac 持续集成等场景出发,给出一套可重复、可重启恢复、可定位失败原因的验收方案。

AppIntentsTesting 自动测试:2026 远程 Mac 部署指南

Shortcuts 手工验证通过,并不代表 App Intents 集成没有回归。本文从 Intent 执行、Entity Query、连续任务、Spotlight 和远程 Mac 持续集成等场景出发,给出一套可重复、可重启恢复、可定位失败原因的验收方案。

最后更新于 2026 年 9 月 1 日,版本信息核实自 Apple Developer 发布记录、Xcode 系统要求与 App Intents Testing 官方文档。

Shortcuts 手工验证正常,但一次 Entity Query 回归直到用户反馈才被发现,这是 App Intents 集成最容易出现的盲区。

症状: Intent 能在本地运行,Siri、Shortcuts 或 Spotlight 却可能静默失效。
最快解法: 把关键链路放进 UI Testing Target,用真实 App 进程执行 AppIntentsTesting 自动测试;需要持续回归时,再部署到工具链固定、可重启恢复并支持无人值守运行的远程 Mac。

这篇指南适合已经接入 App Intents、担心 Siri、Shortcuts 或 Spotlight 功能回归的独立开发者;也适合希望每次提交后自动检查 Intent 与 Entity Query 的小型团队。没有常驻 Apple silicon Mac、却需要持续运行 iOS 集成测试的 Windows 或 Linux 开发者,也可以据此评估远程 Mac 方案。

01

先分清 AppIntentsTesting 覆盖的边界

AppIntentsTesting 不是普通单元测试,也不是把 App Intents 替换成 Mock 后的模拟流程。Apple 的官方说明是:测试代码位于标准 UI Testing Bundle 中,应用运行在独立进程,Intent 在真实 App 进程内执行,测试进程再接收执行结果。官方测试文档

这一区别直接决定了 Target 的放置方式。测试代码通常继承 XCTestCase,通过应用的 Bundle Identifier 找到 Intent、Entity 和 Query 定义,而不是直接导入应用内部模块。应用 Target 与测试 Target 必须使用同一个开发团队进行代码签名,否则测试可能还没有开始执行,就在安装或启动阶段失败。Apple 的 App Intents Testing 文档

最小通过基线应选择一个没有网络、数据库和个人账号依赖的 Intent。例如创建一个固定名称的测试对象,然后验证返回的 Entity 标题。第一轮不要急着加入 Spotlight 或复杂参数,先把以下三类结果分别记录下来:

  • 发现失败:测试无法通过 Bundle Identifier 找到目标 Intent。
  • 参数转换失败:Intent 被发现,但字符串、枚举或自定义值无法转换为目标参数类型。
  • 执行失败:参数已经建立,真实 App 进程执行时抛出错误或返回错误结果。

这三类失败不能混成一个“测试不通过”。在远程 Mac 上,发现失败通常指向 Bundle ID 或构建产物,参数转换失败更多与测试数据定义有关,执行失败才应该优先检查 App Intent 的业务逻辑。

⚠️ 注意: AppIntentsTesting 的测试代码不直接编译应用内部实现,因此参数名称与类型通常没有自动补全。测试文件中的 Intent 名称、参数键名和字符串值应与应用定义保持一致,并在代码审查中单独检查。

02

第一组场景:Intent、Entity 与连续任务

Entity Query 是最值得优先自动化的部分。Shortcuts 中出现“没有可用选项”、搜索不到已有对象,或者用户选择了错误对象,很多时候不是界面问题,而是字符串查询、标识符解析或建议实体返回逻辑出了变化。

建议为每种 Entity 至少建立三条断言:

  1. 字符串查询:输入固定关键词,只返回预期对象。
  2. 标识符解析:传入已知标识符,返回同一个 Entity,而不是新建对象或空值。
  3. 返回字段:检查标题、显示名称、标识符等字段是否仍然对应同一条测试数据。

Apple 在 WWDC26 的示例中展示了 entities(matching:) 形式的查询验证,也演示了让一个 Intent 的结果直接作为另一个 Intent 的输入。WWDC26 AppIntentsTesting 示例

连续任务应模拟真实的 Shortcuts 组合,而不是分别测试两个互不相关的函数。例如:

  • 第一个 Intent 创建测试对象;
  • 测试断言创建结果的标题和标识符;
  • 第二个 Intent 接收第一个 Intent 返回的 Entity;
  • 第二个 Intent 修改对象;
  • 最后重新查询,确认修改已经落入应用数据源。

这样才能发现“第一个 Intent 返回的 Entity 类型与第二个参数不兼容”“查询返回了同名旧对象”“修改操作只更新了界面,没有更新持久化数据”等问题。

测试场景 最小输入 必须断言的结果 失败通常意味着什么
Intent 执行 固定字符串或枚举 返回值、状态、关键字段 Intent 实现或运行环境错误
Entity 字符串查询 固定关键词 数量、标题、标识符 Query 匹配规则回归
标识符解析 固定 ID 返回唯一目标 Entity ID 映射或数据初始化错误
连续 Intent 前一个结果 后一个 Intent 正确接收 参数类型或状态传递错误
建议实体 固定测试数据 建议列表包含预期项 提示数据或排序逻辑变化

测试数据必须固定、可创建、可清理。不能直接读取开发者个人账号里的日历、任务、收藏或云端数据,因为这会让测试结果受到账号状态、同步延迟和历史残留影响。

03

第二组场景:Spotlight 与界面注解

Spotlight 验证要区分三种问题:索引根本没有生成、索引内容已经过期,以及查询逻辑本身没有命中。三者在用户界面上都可能表现为“搜不到”,但修复方式完全不同。

如果应用使用 App Entities 接入 Spotlight,应确认 Entity 具有稳定且唯一的标识符,并在数据变化时更新索引。Apple 文档说明,直接把 App Entity 加入 Spotlight 索引时,系统会依据 Entity 属性构建可搜索内容;如果标识符已经存在,则会更新原有条目,而不是无条件创建新条目。App Entities 接入 Spotlight

验收可以设计成以下顺序:

  • 初始化一个名称不可能与真实用户数据冲突的 Entity;
  • 执行负责创建或索引的测试专用 Intent;
  • 调用 Spotlight 查询,确认只命中这一条测试 Entity;
  • 修改标题后重新索引;
  • 查询旧标题和新标题,确认结果符合产品预期;
  • 删除测试数据后,再次确认索引不会留下可点击的幽灵结果。

如果项目仍使用 Core Spotlight,需要把索引生命周期单独记录。Apple 明确指出,Core Spotlight 索引由应用负责维护,索引内容保留在设备上,不会自动成为 Apple 服务器上的通用索引,也不会在设备之间同步。Core Spotlight 官方说明

界面注解则是另一层检查。测试专用 Intent 先导航到确定页面,再通过 UI 检查页面确实打开,最后读取 View Annotation 暴露的 Entity。这样可以发现页面显示的是“订单 A”,但注解错误地绑定成“客户 A”的问题。

这里不要把 AppIntentsTesting 的结果误认为完整用户体验。它能验证系统集成代码是否返回正确对象,却不能完整代替 Siri 的自然语言理解、Shortcuts 的参数呈现,也不能代替人在真实设备上确认 Spotlight 搜索结果的视觉和交互表现。Apple 推荐先用 AppIntentsTesting 验证基础逻辑,再检查 Shortcuts、Spotlight,最后进行 Siri 人工验证。App Intents 系统体验测试流程

04

第三步:用测试专用 Intent 隔离数据和状态

要让测试具备可重复性,最有效的方式不是在每个测试方法里堆很多清理代码,而是提供一组只用于测试的 Intent。

测试专用 Intent 可以负责:

  • 创建一组固定的 Entity;
  • 删除本次测试产生的数据;
  • 跳转到确定页面;
  • 重置应用内部状态;
  • 包装尚未接入 App Intents 的数据管理逻辑。

这类入口必须同时满足两个条件:使用 isDiscoverable: false,并通过 #if DEBUG 限制在调试构建中。这样它不会被正常用户在 Siri、Shortcuts 或其他系统入口中发现,发布构建也不会意外暴露测试能力。

测试数据建议采用如下规则:

  • 项目标识使用占位符,例如 com.example.sampleapp
  • 测试账号使用专用账号,不使用个人 Apple Account;
  • 测试对象名称使用固定前缀,例如 UITest-Entity-001
  • 文件路径只使用临时目录,不写入开发者主目录;
  • 日志中隐藏 Bundle ID、账号、Token、证书路径和真实业务数据;
  • 每条测试在开始时初始化,在结束时清理,不依赖上一次测试留下的状态。

并发执行时尤其要避免共享模拟器状态。两个测试同时创建同名对象、一个测试删除另一个测试的数据,都会制造偶发失败。除非已经为数据隔离和标识符生成建立严格规则,否则 AppIntentsTesting 任务应先串行运行,等基础稳定后再评估并行。

05

第四步:把任务放进远程 Mac 持续集成

AppIntentsTesting 可以接入持续集成,但“能执行”与“适合无人值守运行”不是一回事。远程 Mac 节点至少要固定以下条件:

  • Xcode 版本与项目要求一致;
  • macOS 版本满足 Xcode 要求;
  • iOS Simulator 运行时已经安装;
  • 应用 Target 与 UI Testing Target 使用同一个 Team;
  • 测试账号、签名身份和钥匙串状态可在重启后恢复;
  • 测试数据初始化和清理不依赖人工点击;
  • 每次任务都保存 xcresult、控制台日志和节点环境信息。

截至 2026 年 9 月 1 日,Apple 的发布记录显示,Xcode 27 beta 6 于 2026 年 8 月 24 日发布,iOS 27 beta 8 于 2026 年 8 月 31 日发布;Xcode 系统要求页面列出 Xcode 27 beta 6 需要 macOS Tahoe 26.4 或更高版本,并包含 iOS 27 SDK。Apple 发布记录Xcode 系统要求

因此,远程节点不要只写“安装最新版 Xcode”。应把实际版本、SDK、模拟器运行时和构建号写入验收日志。Beta 阶段 API、工具链行为和已知问题都可能变化,不能把当前测试结果承诺成长期稳定能力。

代码签名是远程部署中最容易被低估的故障源。应用能在本地运行,不代表远程 Mac 上的测试 Target 也能安装;缺少私钥、Team 选错、Bundle ID 不一致、Provisioning Profile 过期,都可能在测试执行前失败。Apple 建议通过 Xcode 的账户和证书管理功能同步签名身份;如果证书存在但缺少对应私钥,该身份仍然不能用于签名。同步代码签名身份的官方说明

路由方式 适合任务 优点 主要风险 建议评分
本地 Mac 手动执行 开发中的单次调试 反馈快,查看界面方便 容易漏测,依赖个人环境 3 / 5
普通 CI 构建节点 单元测试、编译、静态检查 适合每次提交自动执行 未必保留模拟器与登录状态 3.5 / 5
专用远程 Mac 节点 AppIntentsTesting、Spotlight、连续 Intent 可固定工具链并长期运行 需要管理签名、重启和日志 4.5 / 5
Beta 独立验收节点 iOS 27 与 Xcode 27 兼容性回归 不影响正式发布环境 Beta 行为可能变化 4 / 5

持续集成任务最好拆成四条路由,而不是把所有测试塞进一个脚本:

  1. 普通单元测试:检查纯业务逻辑和数据转换。
  2. UI 自动化:检查关键页面和用户操作路径。
  3. AppIntentsTesting:检查 Intent、Entity、Query、连续调用和部分系统集成。
  4. 正式签名发布任务:检查归档、导出、上传和发布权限。

这样做的价值在于失败含义更清楚。单元测试失败通常不需要启动模拟器;AppIntentsTesting 失败要看应用进程和测试进程日志;正式签名任务失败则优先检查证书、Profile 和发布权限。

远程节点的日志保存不能只保留终端最后几行。xcresult 应作为每次任务的主要产物,同时保存测试目标、提交哈希、Xcode 构建号、SDK、模拟器设备标识、macOS 版本和签名检查结果。这样即使不持续观看远程桌面,也能判断是 Query 回归、索引延迟、签名失效,还是节点重启后环境没有恢复。

如果团队还需要建设通用的 iOS 测试节点,可以参考 iOS 自动化测试服务器部署思路;若重点是长期保留 Xcode 27、模拟器和签名状态,则应优先按 远程 Mac 配置与使用方案 的思路建立独立节点,而不是把 Beta 工具链覆盖到正式打包机上。

06

最小验收集与采用边界

建议先建立一组不追求数量、但能覆盖关键风险的最小验收集:

  • 一个无外部依赖的基础 Intent 执行;
  • 一个 Entity 字符串查询;
  • 一个标识符解析;
  • 两个相互传递 Entity 的连续 Intent;
  • 一个 Spotlight 查询;
  • 一个 View Annotation 检查;
  • 一次远程 Mac 重启后的完整复测;
  • 一次 xcresult 和环境日志留存检查。

项目只是在本地试用 App Intents 时,不必立刻部署常驻远程测试环境;每次提交都已经依赖 Siri、Shortcuts 或 Spotlight 集成时,应把 AppIntentsTesting 接入提交检查;如果团队需要在夜间、周末或无人值守期间持续验证 iOS 27,则可以部署专用远程 Mac 节点。

Beta 阶段应保留回退路径。正式发布任务不要依赖唯一的 Xcode 27 Beta 节点,也不要把测试专用 Intent 带入 Release 构建。等 Xcode 27 RC 或正式版发布后,需要重新核对 API、Target 类型、签名要求、模拟器运行时和测试结果,不能只因为 Beta 阶段“全绿”就跳过复审。

独立开发者的采用评分

  • 1 分: 只有基础 Intent,没有自动化回归。
  • 2 分: 已覆盖 Entity Query,但测试数据依赖个人账号。
  • 3 分: 已接入 UI Testing Target,并能在本地稳定执行。
  • 4 分: 已接入持续集成,保存 xcresult 和环境日志。
  • 5 分: 具备测试专用 Intent、重启恢复、Spotlight 验证、签名隔离和人工 Siri 抽查。

达到 3 分,说明可以开始把关键链路放进每次提交;达到 4 分,才适合交给远程 Mac 无人值守运行;达到 5 分,才算形成可维护的系统能力回归闭环。

07

常见问题

为什么 AppIntentsTesting 必须放在 UI Testing Target?

因为它需要通过真实 App 进程执行 Intent,而不是直接调用应用内部实现。UI Testing Target 提供了跨进程测试基础设施;测试代码只通过 Bundle Identifier 找到应用定义,因此能够覆盖真实的 Intent 参数转换和执行链路。官方 Target 要求说明

它可以放进持续集成流水线吗?

可以,但节点必须具备可重复的工具链和状态。除了 Xcode 与模拟器运行时,还要检查登录会话、签名团队、钥匙串、测试 Target 安装能力,以及重启后是否能恢复。持续集成任务应将 AppIntentsTesting 与普通单元测试和正式签名发布分开。

Entity Query 和参数传递该怎么设计测试?

先用固定数据测试字符串查询、标识符解析和返回字段,再把第一个 Intent 的 Entity 传给第二个 Intent。不要从个人账号读取历史对象;使用测试专用 Intent 初始化数据,并在测试结束后清理,才能避免并发和残留状态造成偶发失败。

在远程 Mac 上跑这类测试,代码签名怎么管?

应用 Target 和 UI Testing Target 选择同一个 Team,Bundle Identifier 指向实际测试应用,并确保远程节点拥有可用的证书与私钥。重启后重新检查钥匙串、Provisioning Profile 和应用安装结果;证书文件存在但缺少私钥时,仍然无法完成签名。

AppIntentsTesting 能替代 Siri 和 Shortcuts 人工验证吗?

不能。它适合自动检查 Intent、Entity、Query、连续任务、Spotlight 查询和界面注解,但 Siri 的自然语言理解、Shortcuts 的参数呈现和用户操作感受仍属于最终体验测试。Beta 工具链期间,人工验证更不能省略。

如果当前方案只是本地 Mac 手动验证,真实缺点通常是测试依赖个人电脑、无法稳定覆盖每次提交,而且重启、系统升级或账号状态变化后很难复现问题;如果改用临时共享环境,又会遇到签名身份、模拟器状态和日志留存不受控的问题。完成最小测试链路后,建议先下载本文的验收项,用自己的 App Intents 测试集连续执行并重启复测;手边没有可常驻运行 Xcode 27 的 Apple silicon Mac 时,再考虑按周期租用 VNCMac 的独立远程 Mac,作为专用测试节点,而不是立刻购买一台只在夜间运行的设备。可从 VNCMac 远程 Mac 入口 了解适合临时测试、持续集成和远程 iOS 打包的使用方式。