Testing CloudKit

I am working on an app update for Pinbook which will bring iCloud sync between iPhone and Apple Watch. I never used CloudKit and CKSyncEngine in the past. After I finished refactoring my app to allow sync I had a problem running unit tests. Here’s what I learned.

  1. The Simulator needs to be signed in to the iCloud account. I used a separate Apple ID which I use on all my test devices. Some say you also need to be logged in to iCloud.com with Safari on the Mac.
  2. The test target needs to have a Host Application selected.
  3. Finally, if you experience test stalling, try running on a different simulator.

The last one really got me and I spent way too much time looking in other places when simply choosing a different simulator fixed my issue. I had some test code which cleaned the iCloud container before the test starts. This test code never stopped running stalling the test.

override func setUp() async throws {
    try await super.setUp()

    // Clear out the server data before every test.
    // This makes sure each test starts out with a clean database.
    //
    // Note that this is potentially dangerous if you're running tests for an app with real precious data in it.
    // When building your own tests, you might want something slightly smarter.
    // For example, your tests might save data to a special test zone, or even a completely separate test container.
    print("test setup start")
    let zoneID = CKRecordZone.ID(zoneName: Pin.zoneName)
    try await PinbookDataStore.container.privateCloudDatabase.deleteRecordZone(withID: zoneID)
    print("test setup end")
}

When I ran my test I saw “test setup start” but didn’t see “test setup end”. Only choosing a new simulator fixed the problem.

Code taken from Apple sample project.