AWS Mobile Blog

Test User Interfaces in iOS Apps with XCTest UI and AWS Device Farm

by Asha Chakrabarty | on | Permalink | Comments |  Share

With AWS Device Farm, you can quickly start testing your Android, iOS, and FireOS apps on real devices in the AWS Cloud. Choose to start an interactive session with a device or run automated tests on many devices at once. AWS Device Farm will provide the results of your tests including pass/fail status, logs, performance metrics, screenshots, and videos.

Introduction to XCTest UI

As of Xcode 7, you can access UI testing capabilities (XCUI) integrated into the Xcode IDE. This functionality allows you to find and interact with UI elements in your app and confirm their properties and states. A few new features make it possible for you to programmatically test and exercise the UI of an iOS app with:

  • New Xcode target type for UI tests:

To set up a UI test in Xcode, you create an Xcode target with the iOS UI Testing Bundle template. The Xcode target type fulfills the special requirements required by the UI tests, including launching a proxy for the application in a separate process and providing accessibility permissions.

  • UI testing APIs include three key classes:

    • XCUIElementQuery: Every UI element is backed by the ability to query its properties. For this reason, each XCUIElement must be unique.
    • XCUIElement: A proxy object for a UI element that is represented as types (for example, a cell or a button).
    • XCUIApplication: An instantiation of your application object that forms the origin for finding UI elements.
  • UI recording:

This allows you to record interactions with your app’s user interface. Xcode will transform these interactions into source code that can be included in your existing tests or to create new tests. 

AWS Device Farm now allows you to run the UI Testing feature incorporated in Xcode 7 on real devices in the AWS Cloud. In this post, we will walk you through how to create an XCTest UI test, package it for testing on AWS Device Farm, schedule a run, and view test results from real devices in the cloud.

Prerequisites

  • You’ll find the sample iOS app used in this post on AWS Labs on GitHub.
  • UI Testing was introduced in Xcode 7 and iOS 9, so be sure to update accordingly.
  • iOS devices must be enabled for development and connected to a host running Xcode.
  • It is assumed that you have created the .ipa file for the sample iOS app before you schedule a run in AWS Device Farm.

Step 1: Create a UI Test for the AWS Sample iOS App

After you have downloaded and opened the sample app in Xcode, build the project. After the build is successful, you will create a new a target type for the UI tests.

Your project navigator should look like the following:

With UI testing, you can record interactions within your app and Xcode will write the code required to re-enact those interactions in your test. You will still need to use XCTAssert to add your test assertions. You can record interactions with your UI by pressing the record button (the small red dot at the bottom left corner of the editor pane).

Copy the following UI test code to your AWSDeviceFarmiOSReferenceAppUITests.m implementation file.

#import 

@interface AWSDeviceFarmiOSReferenceAppUITests : XCTestCase

@end

@implementation AWSDeviceFarmiOSReferenceAppUITests

- (void)setUp {
    
    [super setUp];
    self.continueAfterFailure = NO;
    [[[XCUIApplication alloc] init] launch];
    
}


- (void)tearDown {
    
    [super tearDown];
}


- (void)testNativeInput {
    
    XCUIApplication *app = [[XCUIApplication alloc] init];
    XCUIElementQuery *tabBarsQuery = app.tabBars;
    [tabBarsQuery.buttons[@"Native"] tap];
    
    XCUIElementQuery *collectionViewsQuery = app.collectionViews;
    [collectionViewsQuery.staticTexts[@"Table of elements"] tap];
    [app.navigationBars[@"ElementsTableView"].buttons[@"Menu"] tap];
    [collectionViewsQuery.staticTexts[@"Scrolling View"] tap];
    [app.navigationBars[@"Scrolling View"].buttons[@"Menu"] tap];
    [tabBarsQuery.buttons[@"Home"] tap];
    
}


- (void)testNestedView {
    
    
    XCUIApplication *app = [[XCUIApplication alloc] init];
    XCUIElementQuery *tabBarsQuery = app.tabBars;
    [tabBarsQuery.buttons[@"More"] tap];
    [app.staticTexts[@"Nested"] tap];
    
    XCUIElement *moreNavigationBar = app.navigationBars[@"More"];
    XCUIElement *nextButton = moreNavigationBar.buttons[@"Next"];
    [nextButton tap];
    [nextButton tap];
    [nextButton tap];
    
    XCUIElement *backButton = [[[moreNavigationBar childrenMatchingType:XCUIElementTypeButton] matchingIdentifier:@"Back"] elementBoundByIndex:0];
    [backButton tap];
    [backButton tap];
    [backButton tap];
    [moreNavigationBar.buttons[@"More"] tap];
    [tabBarsQuery.buttons[@"Home"] tap];
    
}


- (void)testAlertControl {
    
    
    XCUIApplication *app = [[XCUIApplication alloc] init];
    XCUIElementQuery *tabBarsQuery = app.tabBars;
    [tabBarsQuery.buttons[@"More"] tap];
    [app.staticTexts[@"Alerts"] tap];
    [app.buttons[@"Modal"] tap];
    [app.buttons[@"OK"] tap];
    [app.buttons[@"Alert"] tap];
    [app.alerts[@"Alert"].collectionViews.buttons[@"OK"] tap];
    [app.navigationBars[@"More"].buttons[@"More"] tap];
    [tabBarsQuery.buttons[@"Native"] tap];
    [app.collectionViews.staticTexts[@"Image Gallery"] tap];
        
}

@end

Before packaging your test for AWS Device Farm, be sure to build the project with Xcode. Use the Product/Build for Running option select an iOS device. Keep in mind that the Build Active Architecture setting for your app and your UI test targets should be the same.

Step 2: Package Your Test for AWS Device Farm

When packaging your test for upload to AWS Device Farm, make sure your iOS XCTest UI Runner test runner bundle is contained in a correctly formatted .ipa file. For more information, see the AWS Device Farm documentation. You can also view the creation of an .ipa file on AWS Labs on GitHub.

Make sure that you package your test in the Payload folder under debug-iphoneos as shown here. In the following screenshot, we renamed the resulting zip file of the Payload folder to UITest.ipa for easier file management.

Step 3: Schedule a Run in AWS Device Farm

Sign in to the AWS Device Farm console and create a run under a new or existing project. Upload the .ipa file of the sample app.

In the next step, you will choose XCTest UI as the test type and upload the .ipa file you created in step 2.

Select the devices on which you’d like to test. If you like, you can create a new device pool for your test run to reuse in subsequent runs.

Finally, review and start the test run.

Step 4: View XCTest UI Test Results

When your test run is complete, you will see the test results summary.

Choose a device to examine its test suites. Here we are reviewing the test suite results for an Apple iPhone 5s and Apple iPhone 6 device.

The results for each device will contain screenshots, video recordings, performance data, and log files that can be downloaded for further review.

Conclusion

We are always happy to hear your feedback. Feel free to leave your feedback, including questions, in the comments or on our developer forum.

Happy testing!