How to Set Up Xcode UI Testing for Today Extensions

Blog

April 17, 2018

TABLE OF CONTENTS

Introduction

Today Extensions are a great way to add quick and glanceable UI to your app. Xcode UI Testing, along with iOSSnapshotTestCase (previously named FBSnapshotTestCase), is a great way to test UI in your app. So, why not use them together? Well, there are a few problems with that.

First, Xcode doesn’t allow a Today Extension target to be set as the target application for a UI Test. Second, iOSSnapshotTestCase doesn’t work out of the box with Xcode UI Testing.

I will cover workarounds for both of these issues below.

Manipulating the World Outside of Your App

Since Xcode doesn’t allow a Today Extension target to be set as the target application for a UI Test, we need a way to get to the Today Extension after the app has launched. While using Xcode UI Test recorder is usually a great start to creating a UI Test, it won’t work without some tweaking. For one thing, it doesn’t record hitting the home button to get to the home screen. Getting to the homescreen and controlling it used to be fairly difficult and involved imported private headers, but now it’s easy—just call XCUIDevice.shared.press(XCUIDevice.Button.home). Then, once on the home screen, it records:


let scrollView = XCUIApplication().otherElements["Home screen icons"].otherElements["SBFolderScalingView"].children(matching: .scrollView).element

scrollView.swipeRight()

The problem here is that XCUIApplication is SpringBoard and not the current target application, so the test runner isn’t able to find “Home screen icons.” To fix this, we need to find SpringBoard’s scroll view like this:


XCUIDevice.shared.press(XCUIDevice.Button.home)

XCUIDevice.shared.press(XCUIDevice.Button.home) //Do this twice to go to the first home screen

let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")

let scrollView = springboard.otherElements["Home screen icons"].otherElements["SBFolderScalingView"].children(matching: .scrollView).element

scrollView.swipeRight() //Swipe over to the Today view

Now we have the Today View on screen. Note that this method is also useful for manipulating other apps, like Settings, in order to test permission changes, such as notifications settings for an app.

Getting iOSSnapshotTestCase to Play Nice with Xcode UI Testing

Typically, iOSSnapshotTestCase is used in a white box testing scenario in which a programmatically-created view is compared to a screenshot previously captured using iOSSnapshotTestCase in record mode. However, Xcode UI Testing is used in a black box testing scenario in which the running app is inspected.

To get set up, follow the instructions in iOSSnapshotTestCase’s ReadMe—except you will want to add iOSSnapshotTestCase to your UI Test target, instead of just your Unit Test target. To bridge the gap between the iOSSnapshotTestCase and Xcode UI Testing, simply create a UIImageView with an image captured during UI Testing:


sleep(1) //wait for swipe animation to finish

let image = springboard.screenshot().image

FBSnapshotVerifyView(UIImageView(image: croppedImage))

Next, set iOSSnapshotTestCase record mode to Yes, run the test, set record mode to No, run the test and … the test failed. Well, the test probably failed because taking a screenshot of the SpringBoard includes the status bar with the time, which more than likely changed since the reference screenshot was recorded.

To avoid this external state change, we need to crop the status bar out of the image. Fortunately, cropping the status bar is easy with Joseph Susnick’s UIImage extension. Add the extension to your UI Test target, and then call removingStatusBar on the screenshot image:


sleep(1) //wait for swipe animation to finish

let croppedImage = springboard.screenshot().image.removingStatusBar

FBSnapshotVerifyView(UIImageView(image: croppedImage))

It took a few hoops to jump through, but now you can verify the look and feel of your Today Extension.

Authored By

Steve Moser

Engineering Manager

RECOMMENDED CONTENT

Enabling Agile Operational Readiness by Embracing Creators

Blog

2020 Legacy Modernization Report

Report

Video Series: The State of the Insurance Industry

Blog

Meet our Experts

Steve Moser
Engineering Manager

Steve Moser is an Engineering Manager at Levvel focusing mainly on iOS. He is passionate about leveraging software to deliver great experiences.

Related Content

Enabling Agile Operational Readiness by Embracing Creators

Southern Fried Agile hosted its annual Agile-focused conference in Charlotte, NC, to bring together the Agile community. Organizations struggle to adopt Agile; however, it’s important to understand and adapt to become a better business.

Blog

Jul 22

2020 Legacy Modernization Report

This report highlights the symptoms of outdated legacy systems for organizations, and offers vital business solutions and strategies on legacy modernization and improving business success.

Report

Jul 14

Let's chat.

You're doing big things, and big things come with big challenges. We're here to help.

Access the Blog

By clicking the button below you agree to our Terms of Service and Privacy Policy.

levvel mark white

Let's improve the world together.

levvel-mark-mint

© Levvel 2020