I contacted Apple, and they found the solution for a device, but not for a simulator.
I did the following steps:
Setup in Xcode a completely new Single View App project and include UI tests. Call it „EntitlementUITest“.
This will create in the project navigator a folder called „EntitlementUITestUITests“.
Select in this folder „EntitlementUITestUITests.swift“.
There is a function testExample()
. Add in this function the line
let _ = CKContainer(identifier: "iCloud.com.yourid.EntitlementUITest")
yourid
is e.g. your company name.
This is the statement that causes the run time error if the project has not been prepared as laid out below.
Select in the project navigator the project.
This will display an additional pane with the project and the targets.
There are 2 targets: The main target „EntitlementUITest“ and the UI test target „EntitlementUITestUITests“.
Select the main target „EntitlementUITest“.
In the top bar of the window right of the pane, select „Capabilities“. You will see that you can select iCloud usage.
Now select the test target „EntitlementUITestUITests“. The top bar now does not have „Capabilities“. This means, the setup that allows your UI tests to use iCloud is much more complicated, and has to be done manually.
First, one needs an entitlements file that specifies the capabilities that the app wants to use. I manually created the following file (actually, I copied the entitlements file of the main target and edited it):
<?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>
I added this file to the project.
In order to allow the UI test target to use iCloud, one needs now a few action in the development center.
In your web browser, open the development center, and open there „Certificates, Identifiers & Profiles“.
The test target is treated as a new app. Thus, it needs a separate app ID.
Open App IDs, and add a new ID „EntitlementUITestUITests“.
It should be an „Explicit App ID“ that uses the bundle ID of your test target, here
com.yourid.EntitlementUITest.
Enable iCloud and Push notifications.
I am not sure if Push Notifications are required, but Apple told me to do so. Probably, you can omit it in the entitlements file and here.
If it is present, please ensure that a valid certificate is specified for the push notification service.
When you enable iCloud, ensure that iCloud.com.yourid.EntitlementUITest
is the only one selected among the assigned iCloud containers.
Create next a new development provisioning profile (one that uses your iOS developer certificate) and associate with com.yourid.EntitlementUITestUITests
.
Download the profile.
Back in Xcode, select again target „EntitlementUITestUITests“ with tab General.
In the section Signing, uncheck Automatically manage signing, since this does not work.
In Signing (Debug), select in the drop down menu Provisioning profile to import your just downloaded profile. This will also be selected in the Signing (Release) section.
Now the project should build for testing without errors.
Run the testExample. It should run now without run time error.
Conclusion:
It is possible to access a CKContainer in an UI test, but this is incredibly complicated.
Why is this process not as easy as with the main targets?
Maybe too less developers UI test their iCloud apps, otherwise more enhancement requests to Xcode would have been written…
One more thing: If everything was done right, the test runs only on a device, not on a simulator. Apple said, running this test on a simulator gives unpredictable results. For me, it was predictable - it fails always.