Manually testing HealthKit

Kane
Kin + Carta Created
5 min readNov 27, 2019

Because any app can read and write to the Health store on iOS and watchOS, (with permission from the user), it means that your app has to be ready to respond to changes made out of your app’s control.

This is a relatively new concept in iOS, since generally the sandbox environment apps run in gives you total control over everything that happens.

In this post I’ll focus specifically on a way to manually test HealthKit, which is especially useful if your app responds to events that other apps write to the shared store in the Health app on iOS (and watchOS).

Let’s make a HealthKit app!

Every good post comes with an example.

Let’s start by creating a simple HealthKit app. Fire up Xcode and choose [File] > [New Project] > [iOS] > [Single View App] and then name it FallDetector:

Our fresh new app’s Xcode project

Our app is going to detect when a user falls over (while wearing an Apple Watch), so we can take some action to help them and make sure they’re okay!

Before we can use any HealthKit APIs, we first need to tell Xcode that our app will use it, so click on [Signing & Capabilites] and add the HealthKit capability:

Adding the HealthKit capability

Additionally, we’ll also need to provide a reason for reading from the Health store, so click on the [Info] tab and add a new entry called NSHealthShareUsageDescription with a string value of We want to help you if you fall!:

Adding the usage description

NOTE: If you’re using Xcode 11 for this example you’ll need to delete the `Application Scene Manifest` entry in the Info.plist for this tutorial.

Next, open AppDelegate.swift and replace the existing code with the following:

Replace the existing code in AppDelegate.swift with this!

In the code above, we request permission to read falls when the app launches, and then set up a query that will be called whenever the Health store detects a new fall is added.

Note: In our example, you have to open the app to receive the event after a fall is detected. HealthKit provides a way to automatically notify and launch our app in the background if a fall is detected, but that’s out of the scope of this post!

Go ahead and run the app and accept the permissions to read falls.

Now let’s test it!

So, how do we actually test this?! For an Apple Watch to detect if a user falls, you’d need to either actually fall over (which might be fun the first one or two times), drop your watch and hope the fall algorithms detect it, or maybe smack your hand on the table so hard it hurts.

None of these are a very robust (or safe!) way of testing if a user falls, so what else can we do?

Remember I said that any app can write to the Health store on iOS? We can use that to our advantage!

It might not be immediately obvious, but you can add more than one app target to an Xcode project or workspace, so we’re going to add a new app target (which will be a very simple app) that can run independently of our main app, and use that to write to to the Health store.

In Xcode, click on the FallDetector project in the navigator, then under Targets, click the + to add a new iOS Single View App. Call it FallDetectorTestHelper and click finish:

Adding the test helper app

Now we have two separate apps in the same Xcode project, we can run them independently.

We’re going to keep our FallDetectorTestHelper very simple for this example and just make it write a new fall to the Health store every time it is launched.

Because it’s a real app, we’ll need to give it the same HealthKit capabilities that the FallDetector app does, and also give it a privacy usage description for NSHealthUpdateUsageDescription:

Adding the usage description for the helper app

Once you’ve done that, open the AppDelegate.swift for FallDetectorTestHelper and then add the following code:

Now go ahead and run the FallDetectorTestHelper app and accept the permissions. You’ve now written a new fall to the store, so swap back to the FallDetector app and get the alert that a fall was detected!

NOTE: You can actually add entries manually in the Health app, but this changes between iOS versions and is super fiddly to do. By creating our own super simple helper app we’re in full control, which means our testers can just get on with testing the app’s behaviour, without having to worry about different iOS versions etc.

Wrapping up

This very simple example could be expanded so that the FallDetectorTestHelper app can have some simple UI that allows testers to add different values and types to the Health store, depending on what your app responds to.

Additionally, this could be used for UI testing. Since you can interact with multiple apps with XCTest UI testing, so you can automate HealthKit interactions too.

Since both apps share the same codebase, you can also share code between them so that you’re not duplicating code. This is even easier if you’re splitting your code up into modules, which is something we use extensively at TAB.

--

--

Kane
Kin + Carta Created

Senior multiplatform engineer. If you're not a fan of equality we won't get on.