iOS UI测试目标缺少授权icloud服务

时间:2019-04-11 19:29:47

标签: xcode cloudkit xcode-ui-testing code-signing-entitlements

我有一个使用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权利,但是无法为测试目标设置此类权利。

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

有什么办法解决这个问题吗?

编辑:

为了进行测试,我创建了一个新的包含UI测试的Single View应用。
在应用程序目标中,我仅启用了CloudKit:
enter image description here

在应用程序委托中,我导入了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")
}  

这不起作用,但会出现相同的错误:
enter image description here

1 个答案:

答案 0 :(得分:0)

我联系了Apple,他们找到了设备的解决方案,而不是模拟器的解决方案。
我执行了以下步骤:

在Xcode中设置一个全新的Single View App项目,并包括UI测试。将其称为“ EntitlementUITest”。 这将在项目导航器中创建一个名为“ EntitlementUITestUITests”的文件夹。

在此文件夹中选择“ EntitlementUITestUITests.swift”。
有一个功能testExample()。在此函数中添加

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

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

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

现在选择测试目标“ 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,现在需要在开发中心进行一些操作。

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

测试目标被视为新应用。因此,它需要一个单独的应用ID。
打开应用程序ID,然后添加一个新ID“ EntitlementUITestUITests”。
它应该是使用您测试目标的捆绑包ID的“显式应用ID”,此处

com.yourid.EntitlementUITest.  

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

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

返回Xcode,通过“常规”标签再次选择目标“ EntitlementUITestUITests”。
在“签名”部分中,取消选中“自动管理签名”,因为它不起作用。
在“签名(调试)”中,从下拉菜单“供应配置文件”中选择以导入您刚刚下载的配置文件。这也将在“签名(发布)”部分中选择。

现在,该项目应该可以进行测试而不会出现错误。

运行testExample。它应该立即运行,而不会出现运行时错误。

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

另一件事:如果一切都正确完成,则测试仅在设备上运行,而不在模拟器上运行。苹果公司表示,在模拟器上运行该测试会产生不可预测的结果。对我来说,这是可以预见的-总是失败。