UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24,...

46
UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion

Transcript of UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24,...

Page 1: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

UI testing iOS apps for humans

Jakub TurekJuly 24, 2017

EL Passion

Page 2: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

About me

Jakub Turek

https://jakubturek.com @KubaTurek turekj

1

Page 3: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Agenda

1. Introduction to UI testing.2. Pain points.3. Apple’s built-in XCUITest.4. Snapshot tests with FBSnapshotTestCase.5. Interaction tests with EarlGrey.6. Combining snapshot & interaction testing.

2

Page 4: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Introduction to UI testing

Page 5: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Definition

UI Testing“UI testing gives you the ability to find and interact with the UIof your app in order to validate the properties and state of theUI elements.”Apple Developer

3

Page 6: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Motivation

Unit test UI testGrantee Developer End userInteracts Source code UI controls

- Code works as intended - Feature presenceProves - The API is simple - Correct output

- Proper layout

4

Page 7: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Writing a first UI test

Page 8: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Test case

Tap Animate progress Highlight

−→ −→

5

Page 9: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

UI testing problems (1/2)

What should I assert?

• Texts.• Icons.• Colors.• No progress bars.• Everything.

6

Page 10: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

UI testing problems (2/2)

When should I assert?

1. Wait & sleep.2. Tests failed.3. More wait & even more sleep.4. Tests succeeded.

7

Page 11: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

My initial impressions

Could we hire the Test AutomationEngineer, please?

8

Page 12: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

iOS built-ins

Page 13: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

A little bit of history

9

Page 14: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Automation quiz (1/2)

QuizHow Automation test cases were programmed?

10

Page 15: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Automation quiz (2/2)

AnswerUsing JavaScript, obviously.

var main = target.frontMostApp().mainWindow();var field = main.textFields()["Field"];

if (field.value() != "Input")UIALogger.logFail("Expected Field to have Input value");

elseUIALogger.logPass("Field has Input value");

11

Page 16: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

XCUITest

• Separate test target.• Swift & ObjC APIs forquerying UI elements.

• Black-box testing.• Two apps:

• app under test,• driver.

12

Page 17: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Test case reminder

Tap Animate progress Highlight

−→ −→

13

Page 18: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

XCUITest code

override func setUp() {super.setUp()XCUIApplication().launch()

}

func testNegativeAnswerHighlight() {let app = XCUIApplication()

app.staticTexts["Not really"].tap()

let ticked = app.staticTexts["x Not really"]let predicate = NSPredicate(format: "exists == 1")

expectation(for: predicate, evaluatedWith: ticked, handler: nil)waitForExpectations(timeout: 5.0, handler: nil)

}

14

Page 19: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

XCUITest issues (1/2)

Lots of „minor” issues:

• Super slow execution (≈ 10s startup penalty).• Fragile time-based expectations.• Type unsafe NSPredicate API.• Lack of communication with application sources:

• Passing launch arguments.

• Needs workaround for animations with .repeat option.

15

Page 20: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

XCUITest issues (2/2)

It is impossible to test the presented case.

protocol XCUIElementAttributes {var identifier: String { get }var frame: CGRect { get }var value: Any? { get }var title: String { get }var label: String { get }var elementType: XCUIElementType { get }var isEnabled: Bool { get }var horizontalSizeClass: XCUIUserInterfaceSizeClass { get }var verticalSizeClass: XCUIUserInterfaceSizeClass { get }var placeholderValue: String? { get }var isSelected: Bool { get }

}

16

Page 21: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Snapshot testing

Page 22: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Snapshot testing

Snapshot testingSnapshot testing compares rendered view to a “referenceimage” stored in the source code repository.

17

Page 23: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Snapshot testing workflow

Snapshot testing workflow is “different”:

1. Building a view:• This means no TDD.

2. Recording a reference snapshot.3. Assertion: comparing the view against the reference.

18

Page 24: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

FBSnapshotTestCase

facebook/ios-snapshot-test-case

FBSnapshotTestCase implements:

• Capturing reference snapshots.• Image comparison algorithm.• Visual diffing for expected/actual snapshots.

19

Page 25: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

FBSnapshotTestCase - example

class ViewControllerSnapshotTests: FBSnapshotTestCase {override func setUp() {super.setUp()recordMode = false // assertion, true for capturing

}

func testViewControllerHasCorrectView() {let sut = ViewController(nibName: nil, bundle: nil)sut.view.frame = UIScreen.main.bounds

FBSnapshotVerifyView(sut.view)}

}

20

Page 26: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Visual diff

Expected Got

Diff

21

Page 27: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Device agnostic snapshots

• The tests would fail if executed with different screensizes/densities.

• Device agnostic snapshots compare snapshots onmatching devices.

override func setUp() {super.setUp()isDeviceAgnostic = true // record/verify device agnosticrecordMode = true

}

22

Page 28: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Using FBSnapshotTestCase with Quick

ashfurrow/Nimble-Snapshots

describe("view") {it("has a valid snapshot") {let sut = ViewController(nibName: nil, bundle: nil)sut.view.frame = UIScreen.main.bounds

expect(sut.view).to(haveValidSnapshot()) // recordSnapshot()}

}

23

Page 29: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Use cases

Snapshot testing works great for enforcing correctness of:

• Localization & internationalization.• UI edge cases.• Layout for multiple devices, size classes.

24

Page 30: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Snapshot testing issues

Biggest pain points:

• TDD workflow is not possible.• Tests can go red even though the tested view looks asexpected.

25

Page 31: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Interaction testing with EarlGrey

Page 32: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

EarlGrey

EarlGreyiOS UI Automation testing framework from Google. It isinspired by Espresso for Android.

26

Page 33: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Key characteristics

Different approach than XCUITest:

• White-box testing:• Matchers work on arbitrary properties.• No need to set accessibility labels.

• Auto synchronization:• Assertions on a stable-state views only.• Expect/wait no more.• Synchronizes with networking, animations and operationsby default.

• Objective-C bridged API for Swift.

27

Page 34: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Example test (1/2)

−→log in

28

Page 35: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Example test (2/2)

func testLoginWorks() {EarlGrey.select(grey_kindOfClass(UITextField.self)).atIndex(0).perform(grey_typeText("12345"))

EarlGrey.select(grey_kindOfClass(UITextField.self)).atIndex(1).perform(grey_typeText("Username"))

EarlGrey.select(grey_buttonTitle("Log in")).perform(grey_tap())

EarlGrey.select(grey_text("Is UI testing easy?")).assert(grey_sufficientlyVisible())

}

29

Page 36: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Under the hood

Application state tracking is backed by solid reverseengineering and lots of method swizzling:

• CALayer→ setNeedsDisplay• NSURLConnection→sendAsynchronousRequest:queue:completionHandler:

• UIViewController→ viewWillAppear:• UIAnimation→ markStart:, markStop• Many more...

30

Page 37: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Fast animations

EarlGrey provides a simple API to speed up animations. Result:way faster suite execution.

class FeatureTests: XCTestCase {override func setUp() {super.setUp()GREYTestHelper.enableFastAnimation()

}}

31

Page 38: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Offscreen element matching

Scrolling down the table view.

func testMatchesOffScreenCell() {EarlGrey.select(grey_text("Cell Text"))

.using(grey_scrollInDirection(.down, 50.0),on: grey_kindOfClass(UITableView.self))

.assert(grey_sufficientlyVisible())}

32

Page 39: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Other features

Other interesting EarlGrey features are:

• Changing device orientation.• Layout assertions:

• Verifies conditions like: <ViewA> is to the left of <ViewB>.• Verbose API modelled after NSLayoutConstraint.

• Handles a plethora of interactions: tap, pinch, swipe, etc.• Rendering views to UIImage.

33

Page 40: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Issues

• Application state managed by hand:• EarlGrey test case cannot restart the application.

• No support for 3D-Touch.• EarlGrey cannot interact with system permission dialogs.• Asserting complete view hierarchy is painful.

34

Page 41: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

EarlGrey + snapshots = r

Page 42: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Test case

−→vote

35

Page 43: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Implementation

func testPositiveVoteWorks() {EarlGrey.select(grey_kindOfClass(SingleAnswerView.self))

.atIndex(1)

.perform(grey_tap())

.assert(grey_sufficientlyVisible())

EarlGrey.select(grey_kindOfClass(AnswerPicker.self)).assert(grey_verifyDeviceAgnosticSnapshot())

//.assert(grey_recordDeviceAgnosticSnapshot())}

36

Page 44: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

EarlGreySnapshots

elpassion/EarlGreySnapshots

Collection of snapshot assertions for EarlGrey. Key benefits:

• Asserting complete view hierarchies.• Visual failure diff instead of cryptic log messages.• Great technique to work with legacy code:

• Freezing a couple of critical paths is possible regardless ofthe code quality.

• Slightly faster feedback loop than without the tests at all.

37

Page 45: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Thank you

Thank you for yourattention!

38

Page 46: UI testing iOS apps for humans - Jakub Turek · UI testing iOS apps for humans Jakub Turek July 24, 2017 EL Passion. About me ... • Localization & internationalization. • UI edge

Further reading

Jakub TurekAutomated UI testing for iOS appshttps://jakubturek.com/automated-ui-tests-in-ios-apps/

Orta TheroxSnapshot Testinghttps://www.objc.io/issues/15-testing/snapshot-testing/

EarlGrey TeamGetting started with EarlGreyhttps://github.com/google/EarlGrey/

39