Slide 1

Slide 1 text

Swift Techniques for Testing Kaya Thomas dotSwift 2020

Slide 2

Slide 2 text

How can we make our tests easier to write, easier to understand and less prone to developer errors?

Slide 3

Slide 3 text

• Using enums with UI tests • Function builders with XCTAssert @kthomas901 dotSwift2020

Slide 4

Slide 4 text

• Using enums with UI tests • Function builders with XCTAssert @kthomas901 dotSwift2020

Slide 5

Slide 5 text

Example app @kthomas901 dotSwift2020

Slide 6

Slide 6 text

@kthomas901 dotSwift2020

Slide 7

Slide 7 text

Features @kthomas901 dotSwift2020

Slide 8

Slide 8 text

Features • Comparing three currencies to one base currency @kthomas901 dotSwift2020

Slide 9

Slide 9 text

Features • Comparing three currencies to one base currency • Ability to change which currency is used for the base currency @kthomas901 dotSwift2020

Slide 10

Slide 10 text

Features • Comparing three currencies to one base currency • Ability to change which currency is used for the base currency • Ability to enter the amount of money for the currency conversions @kthomas901 dotSwift2020

Slide 11

Slide 11 text

Features • Comparing three currencies to one base currency • Ability to change which currency is used for the base currency • Ability to enter the amount of money for the currency conversions • Display the names of each country’s currency with their flags @kthomas901 dotSwift2020

Slide 12

Slide 12 text

UI Testing with XCTestCase Search for existing UI elements on the XCUIApplication using: XCUIElementQuery

Slide 13

Slide 13 text

UI Testing with XCTestCase Search for existing UI elements on the XCUIApplication using: XCUIElementQuery Example to find a label with the text “Hello World”: XCUIApplication().staticTexts[“Hello World”]

Slide 14

Slide 14 text

Testing initial state func testInitialState() { XCTAssertTrue(app.staticTexts["Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields["1"].exists) } @kthomas901 dotSwift2020

Slide 15

Slide 15 text

Testing initial state func testInitialState() { XCTAssertTrue(app.staticTexts[“Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields["1"].exists) } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts["Base Currency"].exists)

Slide 16

Slide 16 text

Testing initial state func testInitialState() { XCTAssertTrue(app.staticTexts[“Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields["1"].exists) } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts["United States Dollar"].exists)

Slide 17

Slide 17 text

Testing initial state func testInitialState() { XCTAssertTrue(app.staticTexts["Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists) } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts["United States Dollar"].exists)

Slide 18

Slide 18 text

Testing initial state func testInitialState() { XCTAssertTrue(app.staticTexts["Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists) } @kthomas901 dotSwift2020 XCTAssertTrue(app.textFields["1"].exists)

Slide 19

Slide 19 text

Let’s capture our screen UI in an enum enum AppUI: String { case baseCurrencyView = "Base Currency" case unitedStatesDollarView = "United States Dollar" case euroView = "Euro" case canadianDollarView = "Canadian Dollar" case francView = "Franc" case initialTextField = "1" } @kthomas901 dotSwift2020

Slide 20

Slide 20 text

Extending our enum extension AppUI { var isStaticText: Bool { return XCUIApplication().staticTexts[self.rawValue].exists } var isTextField: Bool { return XCUIApplication().textFields[self.rawValue].exists } }

Slide 21

Slide 21 text

Revisiting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts[“Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists)

Slide 22

Slide 22 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts[“Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists)

Slide 23

Slide 23 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts[“Base Currency"].exists) XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists)

Slide 24

Slide 24 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists) XCTAssertTrue(AppUI.baseCurrencyView.isStaticText)

Slide 25

Slide 25 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertTrue(app.textFields[“1"].exists) XCTAssertTrue(AppUI.baseCurrencyView.isStaticText)

Slide 26

Slide 26 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.textFields[“1"].exists) XCTAssertTrue(AppUI.baseCurrencyView.isStaticText) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText)

Slide 27

Slide 27 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(app.textFields[“1"].exists) XCTAssertTrue(AppUI.baseCurrencyView.isStaticText) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText)

Slide 28

Slide 28 text

Rewriting initial state test func testInitialState() { } @kthomas901 dotSwift2020 XCTAssertTrue(AppUI.baseCurrencyView.isStaticText) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.initialTextField.isTextField)

Slide 29

Slide 29 text

Testing functionality @kthomas901 dotSwift2020

Slide 30

Slide 30 text

Testing functionality @kthomas901 dotSwift2020

Slide 31

Slide 31 text

Without using the enum func testUpdatingBaseCurrencyCell() { XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertFalse(app.staticTexts["Euro"].exists) app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) } @kthomas901 dotSwift2020

Slide 32

Slide 32 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertFalse(app.staticTexts["Euro"].exists) app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists)

Slide 33

Slide 33 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } XCTAssertTrue(app.staticTexts["United States Dollar"].exists) XCTAssertFalse(app.staticTexts["Euro"].exists) app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists)

Slide 34

Slide 34 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } XCTAssertFalse(app.staticTexts["Euro"].exists) app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText)

Slide 35

Slide 35 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } XCTAssertFalse(app.staticTexts["Euro"].exists) app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText)

Slide 36

Slide 36 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } XCTAssertFalse(app.staticTexts["Euro"].exists) app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText)

Slide 37

Slide 37 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertFalse(AppUI.euroView.isStaticText)

Slide 38

Slide 38 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertFalse(AppUI.euroView.isStaticText)

Slide 39

Slide 39 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(app.staticTexts["Euro"].exists) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertFalse(AppUI.euroView.isStaticText)

Slide 40

Slide 40 text

Testing functionality using enum @kthomas901 dotSwift2020 func testUpdatingBaseCurrencyCell() { } app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertFalse(AppUI.euroView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText)

Slide 41

Slide 41 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } }

Slide 42

Slide 42 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists }

Slide 43

Slide 43 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var element: XCUIElement { } if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] }

Slide 44

Slide 44 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var element: XCUIElement { } if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] }

Slide 45

Slide 45 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var element: XCUIElement { } } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] }

Slide 46

Slide 46 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var element: XCUIElement { } } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] }

Slide 47

Slide 47 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var element: XCUIElement { } } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError()

Slide 48

Slide 48 text

Adding to the enum @kthomas901 dotSwift2020 extension AppUI { var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists } var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() } } var element: XCUIElement { } } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError()

Slide 49

Slide 49 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 XCTAssertFalse(AppUI.euroView.isStaticText) app.tables.cells.element(boundBy: 0).tap()

Slide 50

Slide 50 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 XCTAssertFalse(AppUI.euroView.isStaticText) app.tables.cells.element(boundBy: 0).tap()

Slide 51

Slide 51 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 XCTAssertTrue(AppUI.euroView.isWithinTableCell) app.tables.cells.element(boundBy: 0).tap()

Slide 52

Slide 52 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(AppUI.euroView.isWithinTableCell)

Slide 53

Slide 53 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 app.tables.cells.element(boundBy: 0).tap() XCTAssertTrue(AppUI.euroView.isWithinTableCell)

Slide 54

Slide 54 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 XCTAssertTrue(AppUI.euroView.isWithinTableCell) AppUI.euroView.element.tap()

Slide 55

Slide 55 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) AppUI.euroView.element.tap() XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 XCTAssertTrue(AppUI.euroView.isWithinTableCell)

Slide 56

Slide 56 text

Revisiting the functionality test func testUpdatingBaseCurrencyCell() { XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) AppUI.euroView.element.tap() XCTAssertTrue(AppUI.euroView.isStaticText) } @kthomas901 dotSwift2020 XCTAssertTrue(AppUI.euroView.isWithinTableCell) XCTAssertTrue(AppUI.unitedStatesDollarView.isWithinTableCell)

Slide 57

Slide 57 text

Creating an ElementType enum enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020

Slide 58

Slide 58 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 case textField case staticText case tableCellButton

Slide 59

Slide 59 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } }

Slide 60

Slide 60 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } }

Slide 61

Slide 61 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 init?(_ text: String) { } } else if XCUIApplication().staticTexts[text].exists { self = .staticText }

Slide 62

Slide 62 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 init?(_ text: String) { } } else if XCUIApplication().staticTexts[text].exists { self = .staticText }

Slide 63

Slide 63 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 init?(_ text: String) { } } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil }

Slide 64

Slide 64 text

enum ElementType { case textField case staticText case tableCellButton init?(_ text: String) { if XCUIApplication().textFields[text].exists { self = .textField } else if XCUIApplication().staticTexts[text].exists { self = .staticText } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil } } } @kthomas901 dotSwift2020 init?(_ text: String) { } } else if XCUIApplication().tables.cells.buttons[text].exists { self = .tableCellButton } else { return nil }

Slide 65

Slide 65 text

Get XCUIElement from ElementType extension AppUI { var element: XCUIElement { if self.isStaticText { return XCUIApplication().staticTexts[self.rawValue] } else if self.isTextField { return XCUIApplication().textFields[self.rawValue] } else if self.isWithinTableCell { return XCUIApplication().tables.cells.buttons[self.rawValue] } fatalError() }

Slide 66

Slide 66 text

Get XCUIElement from ElementType extension ElementType { func getElement(with text: String) -> XCUIElement { switch self { case .staticText: return XCUIApplication().staticTexts[text] case .textField: return XCUIApplication().textFields[text] case .tableCellButton: return XCUIApplication().tables.cells.buttons[text] } } }

Slide 67

Slide 67 text

Using ElementType extension AppUI { var type: ElementType { guard let type = ElementType(self.rawValue) else { fatalError() } return type } var element: XCUIElement { return type.getElement(with: self.rawValue) } }

Slide 68

Slide 68 text

Using ElementType @kthomas901 dotSwift2020 extension AppUI { } var isStaticText: Bool { return XCUIApplication().staticTexts[self.rawValue].exists } var isTextField: Bool { return XCUIApplication().textFields[self.rawValue].exists } var isWithinTableCell: Bool { return XCUIApplication().tables.cells.buttons[self.rawValue].exists }

Slide 69

Slide 69 text

Using ElementType @kthomas901 dotSwift2020 extension AppUI { } var isStaticText: Bool { return type == .staticText } var isTextField: Bool { return type == .textField } var isWithinTableCell: Bool { return type == .tableCellButton }

Slide 70

Slide 70 text

Recap @kthomas901 dotSwift2020

Slide 71

Slide 71 text

Recap • Use the enum cases to represent the different elements on one screen @kthomas901 dotSwift2020

Slide 72

Slide 72 text

Recap • Use the enum cases to represent the different elements on one screen • Have a computed variable for the element in your enum that you can take actions on @kthomas901 dotSwift2020

Slide 73

Slide 73 text

Recap • Use the enum cases to represent the different elements on one screen • Have a computed variable for the element in your enum that you can take actions on @kthomas901 dotSwift2020 • Create a separate ElementType enum that can be reused for the different enums you have for each screen

Slide 74

Slide 74 text

• Using enums with UI tests • Function builders with XCTAssert @kthomas901 dotSwift2020

Slide 75

Slide 75 text

Function builders Swift 5.1 @kthomas901 dotSwift2020

Slide 76

Slide 76 text

@kthomas901 dotSwift2020

Slide 77

Slide 77 text

func testInitialState() { XCTAssertTrue(AppUI.baseCurrencyView.isStaticText) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.initialTextField.isTextField) } Before: @kthomas901 dotSwift2020

Slide 78

Slide 78 text

func testInitialState() { XCTAssertTrue(AppUI.baseCurrencyView.isStaticText) XCTAssertTrue(AppUI.unitedStatesDollarView.isStaticText) XCTAssertTrue(AppUI.initialTextField.isTextField) } func testInitialState() { assertTrue { AppUI.baseCurrencyView.isStaticText AppUI.unitedStatesDollarView.isStaticText AppUI.initialTextField.isTextField } } Before: After: @kthomas901 dotSwift2020

Slide 79

Slide 79 text

BooleanFunctionBuilder @_functionBuilder class BooleanFunctionBuilder { static func buildBlock(_ children: Bool...) -> [Bool] { return children } } @kthomas901 dotSwift2020

Slide 80

Slide 80 text

Grouping XCAssertTrue & XCAssertFalse @kthomas901 dotSwift2020

Slide 81

Slide 81 text

Grouping XCAssertTrue & XCAssertFalse public func assertTrue(@BooleanFunctionBuilder builder: () -> [Bool]) { let expressions = builder() expressions.forEach { XCTAssertTrue($0) } } @kthomas901 dotSwift2020

Slide 82

Slide 82 text

Grouping XCAssertTrue & XCAssertFalse public func assertTrue(@BooleanFunctionBuilder builder: () -> [Bool]) { let expressions = builder() expressions.forEach { XCTAssertTrue($0) } } public func assertFalse(@BooleanFunctionBuilder builder: () -> [Bool]) { let expressions = builder() expressions.forEach { XCTAssertFalse($0) } } @kthomas901 dotSwift2020

Slide 83

Slide 83 text

Using assertTrue

Slide 84

Slide 84 text

Using assertTrue func testInitialState() { assertTrue { AppUI.baseCurrencyView.isStaticText AppUI.unitedStatesDollarView.isStaticText AppUI.initialTextField.isTextField } }

Slide 85

Slide 85 text

Recap @kthomas901 dotSwift2020

Slide 86

Slide 86 text

Recap • Function builders help make your code more readable and easier to write @kthomas901 dotSwift2020

Slide 87

Slide 87 text

Recap • Function builders help make your code more readable and easier to write • They can be really simple! @kthomas901 dotSwift2020

Slide 88

Slide 88 text

Resources • iOS Automation with XCUITest, free course at Test Automation U by Shashikant Jagtap • Testing Swift by Paul Hudson • Awesome Function Builders Github repo @kthomas901 dotSwift2020

Slide 89

Slide 89 text

Thank you!