UI testing under iOS 11 has the ability to interact with other installed apps. Specifically, XCUIApplication got a new constructor that takes a bundle ID. Let's see how we use this to put our deeplinks under automated tests.

Overview

What you basically do is create a helper-app, MyHelperApp in below examples, that merely holds UIButtons for all the deeplinks your main app, MyApp, should support. For MyApp you register a URL scheme, and for HelperApp you whitelist that very same scheme under the LSApplicationQueriesSchemes key in Info.plist:

Helper App Scheme

The new XCUIApplication constructor allows you to open MyHelperApp...

let helperApp = XCUIApplication(bundleIdentifier: "org.merela.MyHelperApp")
helperApp.activate()
helperApp.buttons[deeplink].tap()

...and there open a particular deeplink that MyApp supports:

let url = URL(string: "\(myAppBundleId)://\(buttonTitle)")
UIApplication.shared.open(url)

Finally, assert that the deeplink opened MyApp in the expected state.

With Xcode 9, check out the sample project. To try it out, first install the HelperApp and then run tests for the MyApp target. Also make sure Simulator's 'Hardware Keyboard' is disabled.

CI considerations

Xcode 9 GM will be released soon, but until then you have to switch to Xcode-beta's toolchain, to be used by xcodebuild commands further below:

sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer

This proof-of-concept script will make sure helper-app is always installed and ready to be used by main-app's UI tests:

HELPER_APP='MyHelperApp'
MAIN_APP='MyApp'

BUILD_DIR="/tmp/$HELPER_APP"
DESTINATION="platform=iOS Simulator,name=iPhone 7 Plus,OS=11.0"

# Build an .app for the helper-app
xcodebuild build                       \
           -destination "$DESTINATION" \
           -target $HELPER_APP         \
           -scheme $HELPER_APP         \
           CONFIGURATION_BUILD_DIR=$BUILD_DIR

# Install the helper-app onto the Simulator
xcrun simctl install booted "$BUILD_DIR/$HELPER_APP.app"

# UI test the main-app
xcodebuild test -scheme $MAIN_APP -destination "$DESTINATION"

Conclusion

One other new API worth mentioning is XCTContext.runActivity(named:block:), which logically groups subparts of each test-case, makes these groups visible in logs, and thus eases debugging:

runActivity context

There's plenty more: performance improvements (firstMatch), screenshots, attachments, etc. - check out WWDC 2017's What's New in Testing.