iOS UI 测试目标缺少权利 icloud-services

iOS UI test target is missing entitlement icloud-services

我有一个使用 iCloud 的应用程序。这很好用。

我现在尝试编写一个 UI 测试,首先检查 iCloud 帐户是否可访问,即用户是否已登录到 iCloud 并为该应用程序启用了 iCloud。

为此,我尝试调用(CloudKit 是导入的)

let container = CKContainer(identifier: kICloudContainerID)
container.accountStatus() { (status, error) in
  // …
}  

然而,当我尝试访问 CKContainer(第一行)时,我收到错误

The application is missing required entitlement com.apple.developer.icloud-services
(null)

当然,我的应用程序设置了 iCloud 权利,但无法为测试目标设置此类权利。

我已阅读。建议的解决方案(禁用断点、切换 iCloud 功能、清除代码签名权利)无效。

知道如何解决这个问题吗?

编辑:

为了测试,我创建了一个新的单视图应用程序,其中包含 UI 个测试。
在应用程序目标中,我只启用了 CloudKit:

在应用程序委托中,我导入了 CloudKit,并访问了 CKContainer:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let container = CKContainer(identifier: "iCloud.com.zeh4soft.EntitlementUITest")
    return true
}  

这行得通。

在 UI 测试中,我还导入了 CloudKit,并添加了相同的行:

func testExample() {
  let container = CKContainer(identifier: "iCloud.com.zeh4soft.EntitlementUITest")
}  

这不起作用,但给出相同的错误:

我联系了 Apple,他们找到了针对设备的解决方案,但没有针对模拟器的解决方案。
我执行了以下步骤:

在 Xcode 中设置一个全新的单视图应用程序项目并包括 UI 测试。称之为“权利UI测试”。 这将在项目导航器中创建一个名为“EntitlementUITestUITests”的文件夹。

Select 在此文件夹“EntitlementUITestUITests.swift”中。
有一个函数testExample()。在此函数中添加行

    let _   = CKContainer(identifier: "iCloud.com.yourid.EntitlementUITest")

yourid 例如您的公司名称。
如果项目未按如下所示准备,则此语句会导致 运行 时间错误。

Select 在项目导航器中项目。
这将显示一个包含项目和目标的附加窗格。
有 2 个目标:主要目标“EntitlementUITest”和 UI 测试目标“EntitlementUITestUITests”。
Select 主要目标“权利UI测试”。
在窗格右侧 window 的顶部栏中,select“功能”。您会看到您可以 select iCloud 使用。

现在 select 测试目标“EntitlementUITestUITests”。顶部栏现在没有“功能”。这意味着,允许 UI 测试使用 iCloud 的设置要复杂得多,并且必须手动完成。

首先,需要一个权利文件来指定应用程序想要使用的功能。我手动创建了以下文件(实际上,我复制了主要目标的权利文件并进行了编辑):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>aps-environment</key>
    <string>development</string>
    <key>com.apple.developer.icloud-container-identifiers</key>
    <array>
        <string>iCloud.com.yourid.EntitlementUITest</string>
    </array>
    <key>com.apple.developer.icloud-services</key>
    <array>
        <string>CloudKit</string>
    </array>
</dict>
</plist>  

我将此文件添加到项目中。

为了让UI测试目标使用iCloud,现在需要在开发中心进行一些操作。

在您的网络浏览器中,打开开发中心,然后打开“证书、标识符和配置文件”。

测试目标被视为新应用。因此,它需要一个单独的应用程序 ID。
打开 App IDs,添加一个新的 ID „EntitlementUITestUITests“.
它应该是一个“明确的应用程序 ID”,它使用你的测试目标的包 ID,这里

com.yourid.EntitlementUITest.  

启用 iCloud 和推送通知。
我不确定是否需要推送通知,但 Apple 告诉我这样做。也许,您可以在权利文件和此处省略它。 如果存在,请确保为推送通知服务指定了有效的证书。
启用 iCloud 时,请确保 iCloud.com.yourid.EntitlementUITest 是分配的 iCloud 容器中唯一的 selected。

接下来创建一个新的开发配置文件(使用您的 iOS 开发人员证书的配置文件)并与 com.yourid.EntitlementUITestUITests 相关联。
下载配置文件。

返回 Xcode,select 再次使用“常规”选项卡定位“权利UI测试UI测试”。
在签名部分,取消选中自动管理签名,因为这不起作用。
在 Signing (Debug) 中,select 在下拉菜单 Provisioning profile 中导入您刚下载的配置文件。这也将 select 编辑在签名(发布)部分。

现在应该可以正确构建项目以进行测试。

运行 测试示例。它应该 运行 现在没有 运行 时间错误。

结论:
可以在 UI 测试中访问 CKContainer,但这非常复杂。
为什么这个过程不像主要目标那么容易?
也许开发人员太少 UI 测试他们的 iCloud 应用程序,否则会向 Xcode 写入更多增强请求…

还有一件事:如果一切都做对了,测试 运行 只在设备上,而不是在模拟器上。 Apple 表示,运行在模拟器上进行此测试会产生不可预测的结果。对我来说,这是可以预见的——它总是失败。