UI TDD COCOAHEADS AUG 2018 TDD UI TDD SOFTWARE TESTING SOFTWARE - - PowerPoint PPT Presentation

ui tdd
SMART_READER_LITE
LIVE PREVIEW

UI TDD COCOAHEADS AUG 2018 TDD UI TDD SOFTWARE TESTING SOFTWARE - - PowerPoint PPT Presentation

COCOAHEADS AUG 2018 TDD UI TDD COCOAHEADS AUG 2018 TDD UI TDD SOFTWARE TESTING SOFTWARE TESTING Repeatability SOFTWARE TESTING INFORMAL MANUAL TESTING Repeatability SOFTWARE TESTING INFORMAL FORMAL MANUAL MANUAL


slide-1
SLIDE 1

UI TDD

COCOAHEADS • AUG 2018

TDD

slide-2
SLIDE 2

UI TDD

COCOAHEADS • AUG 2018

TDD

slide-3
SLIDE 3

SOFTWARE TESTING

slide-4
SLIDE 4

SOFTWARE TESTING

slide-5
SLIDE 5

SOFTWARE TESTING Repeatability

slide-6
SLIDE 6

SOFTWARE TESTING Repeatability

🙐

INFORMAL MANUAL TESTING

slide-7
SLIDE 7

SOFTWARE TESTING Repeatability

🙐

INFORMAL MANUAL TESTING

📌

FORMAL MANUAL TESTING

slide-8
SLIDE 8

SOFTWARE TESTING Repeatability

🙐

INFORMAL MANUAL TESTING

📌

FORMAL MANUAL TESTING

🤗

AUTOMATED TESTING

slide-9
SLIDE 9

SOFTWARE TESTING

AUTOMATED

UNIT

INPUT OUTPUT

slide-10
SLIDE 10

SOFTWARE TESTING

AUTOMATED

UNIT

slide-11
SLIDE 11

SOFTWARE TESTING

AUTOMATED

slide-12
SLIDE 12

SOFTWARE TESTING

AUTOMATED

INTEGRATION

slide-13
SLIDE 13

SOFTWARE TESTING

AUTOMATED

slide-14
SLIDE 14

SOFTWARE TESTING

AUTOMATED

END-TO-END

slide-15
SLIDE 15

SOFTWARE TESTING

AUTOMATED

END-TO-END INTEGRATION UNIT

slide-16
SLIDE 16

SOFTWARE TESTING

AUTOMATED

END-TO-END INTEGRATION UNIT

slide-17
SLIDE 17

SOFTWARE TESTING

AUTOMATED

Time/Complexity

END-TO-END INTEGRATION UNIT

slide-18
SLIDE 18

SOFTWARE TESTING

AUTOMATED

Time/Complexity Realism

END-TO-END INTEGRATION UNIT

slide-19
SLIDE 19

SOFTWARE TESTING

AUTOMATED

END-TO-END INTEGRATION UNIT

Time/Complexity Realism

📳 UI TESTS

slide-20
SLIDE 20

UI TESTS

slide-21
SLIDE 21

UI TESTS

slide-22
SLIDE 22

UI TESTS

slide-23
SLIDE 23

UI TESTS

slide-24
SLIDE 24

UI TESTS

slide-25
SLIDE 25

UI TESTS

slide-26
SLIDE 26

UI TESTS

VERIFY BEHAVIOR

slide-27
SLIDE 27

UI TESTS

BUILT ON ACCESSIBILITY

VERIFY BEHAVIOR

slide-28
SLIDE 28

UI TESTS

VERIFY BEHAVIOR BUILT ON ACCESSIBILITY RECORD TO LEARN

slide-29
SLIDE 29

BETTER UI TESTING

slide-30
SLIDE 30

BETTER UI TESTING

slide-31
SLIDE 31

BETTER UI TESTING

slide-32
SLIDE 32

BETTER UI TESTING Title

slide-33
SLIDE 33

BETTER UI TESTING Button Title

slide-34
SLIDE 34

BETTER UI TESTING Button Title Table

slide-35
SLIDE 35

BETTER UI TESTING Button Title Cell Table

slide-36
SLIDE 36

BETTER UI TESTING Button Button Title Cell Table

slide-37
SLIDE 37

BETTER UI TESTING Button Button Button Title Cell Table

slide-38
SLIDE 38

BETTER UI TESTING Button Button Table Button Title Cell

slide-39
SLIDE 39

BETTER UI TESTING Button Button Table Title Button Title Cell

slide-40
SLIDE 40

BETTER UI TESTING Button Button Table Title Label Button Title Cell

slide-41
SLIDE 41

BETTER UI TESTING Button Button Table Button Title Label Button Title Cell

slide-42
SLIDE 42

BETTER UI TESTING Button Button Table Button Title Label Button Title Cell

slide-43
SLIDE 43

BETTER UI TESTING Button Button Table Button Title Label Tap Button Title Cell

slide-44
SLIDE 44

BETTER UI TESTING Button Button Table Button Title Label Tap Button Title Cell Swipe

slide-45
SLIDE 45

BETTER UI TESTING Button Button Table Button Title Label Tap Tap Button Title Cell Swipe

slide-46
SLIDE 46

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe

slide-47
SLIDE 47

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap

slide-48
SLIDE 48

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap

slide-49
SLIDE 49

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap

slide-50
SLIDE 50

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Text

slide-51
SLIDE 51

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text

slide-52
SLIDE 52

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text Text

slide-53
SLIDE 53

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text Text Text

slide-54
SLIDE 54

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text Text Text Text

slide-55
SLIDE 55

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text Text Title Text

slide-56
SLIDE 56

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text Text Title Text

slide-57
SLIDE 57

BETTER UI TESTING Button Button Button Title Cell Table Button Title Label Tap Tap Tap Swipe Tap Tap Count Text Text Title Text

slide-58
SLIDE 58

BENEFITS

slide-59
SLIDE 59

BENEFITS

EASIER TO READ

slide-60
SLIDE 60

BENEFITS

XCUIApplication().tables.children (matching: .cell).element(boundBy : 0).staticTexts["2018-07-03 20:45:14 +0000"].tap()

Before

EASIER TO READ

slide-61
SLIDE 61

BENEFITS

.tapOnCell(at: 0)

Before After

XCUIApplication().tables.children (matching: .cell).element(boundBy : 0).staticTexts["2018-07-03 20:45:14 +0000"].tap()

EASIER TO READ

slide-62
SLIDE 62

BENEFITS

EASIER TO READ

EASIER TO MAINTAIN

slide-63
SLIDE 63

BENEFITS

EASIER TO READ

EASIER TO MAINTAIN

WRITE TESTS FIRST!

slide-64
SLIDE 64

EASIER TO READ

BENEFITS

EASIER TO MAINTAIN

TDD

WRITE TESTS FIRST!

slide-65
SLIDE 65

TDD

TEST-DRIVEN DEVELOPMENT

slide-66
SLIDE 66

TDD

slide-67
SLIDE 67

TDD

slide-68
SLIDE 68

TDD

 

slide-69
SLIDE 69

TDD

 

slide-70
SLIDE 70

TDD

 

slide-71
SLIDE 71

TDD

 

slide-72
SLIDE 72

TDD

 

slide-73
SLIDE 73

TDD

 

slide-74
SLIDE 74

TDD

 

slide-75
SLIDE 75

TDD

 

slide-76
SLIDE 76

TDD

{ } { }

 

slide-77
SLIDE 77

TDD

{ } { }

 

slide-78
SLIDE 78

CODE

slide-79
SLIDE 79

CODE

slide-80
SLIDE 80

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements // MARK: - Actions // MARK: - Verifications }

slide-81
SLIDE 81

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements // MARK: - Actions // MARK: - Verifications } import XCTest protocol TestPage { var testCase: XCTestCase { get } } extension TestPage { var app: XCUIApplication { return XCUIApplication() } }

slide-82
SLIDE 82

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements // MARK: - Actions // MARK: - Verifications }

slide-83
SLIDE 83

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements // MARK: - Actions // MARK: - Verifications }

slide-84
SLIDE 84

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] } fileprivate var backButton: XCUIElement { return app.navigationBars.buttons["Master"] } ...

slide-85
SLIDE 85

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] } fileprivate var backButton: XCUIElement { return app.navigationBars.buttons["Master"] } ...

Button Label

slide-86
SLIDE 86

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] } fileprivate var backButton: XCUIElement { return app.navigationBars.buttons["Master"] } ...

slide-87
SLIDE 87

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements } fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] } fileprivate var backButton: XCUIElement { return app.navigationBars.buttons["Master"] } ...

slide-88
SLIDE 88

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements } fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] } fileprivate var backButton: XCUIElement { return app.navigationBars.buttons["Master"] } ...

slide-89
SLIDE 89

CODE

import XCTest struct DetailPage: TestPage { let testCase: XCTestCase // MARK: - Elements } fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] } fileprivate var backButton: XCUIElement { return app.navigationBars.buttons["Master"] } ...

slide-90
SLIDE 90

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... } @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

CODE

slide-91
SLIDE 91

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... } @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

CODE Tap

slide-92
SLIDE 92

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... } @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

CODE

slide-93
SLIDE 93

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... }

CODE

@discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-94
SLIDE 94

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... }

CODE

@discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-95
SLIDE 95

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... }

CODE

@discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-96
SLIDE 96

CODE

... func expect(exists element: XCUIElement, file: String = #file, line: UInt = #line) { if !element.exists { recordFailure(withDescription: "Expected \(element) to exist.", inFile: file, atLine: Int(line), expected: true) } } ... @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-97
SLIDE 97

CODE

... func expect(exists element: XCUIElement, file: String = #file, line: UInt = #line) { if !element.exists { recordFailure(withDescription: "Expected \(element) to exist.", inFile: file, atLine: Int(line), expected: true) } } ... @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-98
SLIDE 98

CODE

... func expect(exists element: XCUIElement, file: String = #file, line: UInt = #line) { if !element.exists { recordFailure(withDescription: "Expected \(element) to exist.", inFile: file, atLine: Int(line), expected: true) } } ... @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-99
SLIDE 99

CODE

... func expect(exists element: XCUIElement, file: String = #file, line: UInt = #line) { if !element.exists { recordFailure(withDescription: "Expected \(element) to exist.", inFile: file, atLine: Int(line), expected: true) } } ... @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-100
SLIDE 100

CODE

... func expect(exists element: XCUIElement, file: String = #file, line: UInt = #line) { if !element.exists { recordFailure(withDescription: "Expected \(element) to exist.", inFile: file, atLine: Int(line), expected: true) } } ... @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-101
SLIDE 101

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... }

CODE

@discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

slide-102
SLIDE 102

CODE

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions @discardableResult func tapOnBackButton(file: StaticString = #file, line: UInt = #line) -> MasterPage { XCTAssertTrue(backButton.exists, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) } ... }

slide-103
SLIDE 103

CODE

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions @discardableResult func tapOnBackButton(file: StaticString = #file, line: UInt = #line) -> MasterPage { XCTAssertTrue(backButton.exists, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) } ... }

slide-104
SLIDE 104

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... } @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

CODE

slide-105
SLIDE 105

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... } @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

CODE

slide-106
SLIDE 106

import XCTest struct DetailPage: TestPage { ... // MARK: - Actions ... } @discardableResult func tapOnBackButton(file: String = #file, line: UInt = #line) -> MasterPage { testCase.expect(exists: backButton, file: file, line: line) backButton.tap() return MasterPage(testCase: testCase) }

CODE

slide-107
SLIDE 107

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-108
SLIDE 108

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-109
SLIDE 109

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-110
SLIDE 110

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file:

CODE

// MARK: - Elements fileprivate var detailText: XCUIElement { return app.staticTexts[“DetailViewController.label"] }

slide-111
SLIDE 111

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-112
SLIDE 112

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-113
SLIDE 113

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

Text

slide-114
SLIDE 114

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-115
SLIDE 115

CODE

... // MARK: - Verifications @discardableResult func verifyDetailPageIsShowing(file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) return self } @discardableResult func verifyLabelText(is text: String, file: String = #file, line: UInt = #line) -> DetailPage { testCase.expect(exists: detailText, file: file, line: line) testCase.expect(detailText.label, equals: text, file: file, line: line) return self } ... }

slide-116
SLIDE 116

CODE

slide-117
SLIDE 117

CODE

slide-118
SLIDE 118

CODE

import XCTest class BasicEntryUITests: XCTestCase { }

slide-119
SLIDE 119

CODE

import XCTest class BasicEntryUITests: XCTestCase {

  • verride func setUp() {

super.setUp() continueAfterFailure = false let application = XCUIApplication() application.launchArguments.append("--uitesting") application.launch() } }

slide-120
SLIDE 120

CODE

import XCTest class BasicEntryUITests: XCTestCase {

  • verride func setUp() {

super.setUp() continueAfterFailure = false let application = XCUIApplication() application.launchArguments.append("--uitesting") application.launch() } }

slide-121
SLIDE 121

CODE

import XCTest class BasicEntryUITests: XCTestCase {

  • verride func setUp() {

super.setUp() continueAfterFailure = false let application = XCUIApplication() application.launchArguments.append("--uitesting") application.launch() } }

slide-122
SLIDE 122

CODE

super.setUp() continueAfterFailure = false let application = XCUIApplication() application.launchArguments.append("--uitesting") application.launch() } } class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if CommandLine.arguments.contains("--uitesting") { // Set up state for UI testing } ... } }

slide-123
SLIDE 123

CODE

super.setUp() continueAfterFailure = false let application = XCUIApplication() application.launchArguments.append("--uitesting") application.launch() } } class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if CommandLine.arguments.contains("--uitesting") { // Set up state for UI testing } ... } }

slide-124
SLIDE 124

CODE

import XCTest class BasicEntryUITests: XCTestCase {

  • verride func setUp() {

super.setUp() continueAfterFailure = false let application = XCUIApplication() application.launchArguments.append("--uitesting") application.launch() } }

slide-125
SLIDE 125

CODE

... func testAddingEntry() { }

slide-126
SLIDE 126

CODE

... func testAddingEntry() { MasterPage(testCase: self) }

slide-127
SLIDE 127

CODE

... func testAddingEntry() { MasterPage(testCase: self) .verifyMasterPageIsShowing() }

slide-128
SLIDE 128

CODE

... func testAddingEntry() { MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) }

slide-129
SLIDE 129

CODE

... func testAddingEntry() { MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() }

slide-130
SLIDE 130

CODE

... func testAddingEntry() { MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) }

slide-131
SLIDE 131

CODE

... func testAddingEntry() { MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: ) }

slide-132
SLIDE 132

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) }

slide-133
SLIDE 133

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) }

slide-134
SLIDE 134

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() }

slide-135
SLIDE 135

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: nowLabel) }

slide-136
SLIDE 136

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: nowLabel) .tapOnBackButton() }

slide-137
SLIDE 137

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: nowLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-138
SLIDE 138

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: nowLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-139
SLIDE 139

CODE

... func testAddingEntry() { let nowLabel = String(describing: Date()) MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: nowLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: nowLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

Expected ‘Optional(…
slide-140
SLIDE 140

CODE

... func testAddingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: zeroLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-141
SLIDE 141

CODE

... func testAddingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: zeroLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-142
SLIDE 142

CODE

... func testAddingAndDeletingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: zeroLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-143
SLIDE 143

CODE

... func testAddingAndDeletingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: zeroLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-144
SLIDE 144

import XCTest struct MasterPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate func cell(at index: Int) -> XCUIElement { return table.cells.element(boundBy: index) } fileprivate func deleteButton(for cell: XCUIElement) -> XCUIElement { return cell.buttons["Delete"] } ...

slide-145
SLIDE 145

import XCTest struct MasterPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate func cell(at index: Int) -> XCUIElement { return table.cells.element(boundBy: index) } fileprivate func deleteButton(for cell: XCUIElement) -> XCUIElement { return cell.buttons["Delete"] } ...

Button

slide-146
SLIDE 146

import XCTest struct MasterPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate func cell(at index: Int) -> XCUIElement { return table.cells.element(boundBy: index) } fileprivate func deleteButton(for cell: XCUIElement) -> XCUIElement { return cell.buttons["Delete"] } ...

slide-147
SLIDE 147

import XCTest struct MasterPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate func cell(at index: Int) -> XCUIElement { return table.cells.element(boundBy: index) } fileprivate func deleteButton(for cell: XCUIElement) -> XCUIElement { return cell.buttons["Delete"] } ...

slide-148
SLIDE 148

import XCTest struct MasterPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate func cell(at index: Int) -> XCUIElement { return table.cells.element(boundBy: index) } fileprivate func deleteButton(for cell: XCUIElement) -> XCUIElement { return cell.buttons["Delete"] } ...

slide-149
SLIDE 149

import XCTest struct MasterPage: TestPage { let testCase: XCTestCase // MARK: - Elements }

CODE

fileprivate func cell(at index: Int) -> XCUIElement { return table.cells.element(boundBy: index) } fileprivate func deleteButton(for cell: XCUIElement) -> XCUIElement { return cell.buttons["Delete"] } ...

slide-150
SLIDE 150

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-151
SLIDE 151

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE Tap

slide-152
SLIDE 152

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-153
SLIDE 153

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-154
SLIDE 154

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-155
SLIDE 155

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-156
SLIDE 156

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-157
SLIDE 157

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-158
SLIDE 158

import XCTest struct MasterPage: TestPage { ... // MARK: - Actions ... } @discardableResult func deleteCell(at index: Int, file: String = #file, line: UInt = #line) -> MasterPage { let cell = self.cell(at: index) testCase.expect(exists: cell, file: file, line: line) cell.swipeLeft() let deleteButton = self.deleteButton(for: cell) testCase.expect(exists: deleteButton, file: file, line: line) deleteButton.tap() return self }

CODE

slide-159
SLIDE 159

CODE

... func testAddingAndDeletingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) // Detail page .verifyDetailPageIsShowing() .verifyLabelText(is: zeroLabel) .tapOnBackButton() // Master page .verifyMasterPageIsShowing() }

slide-160
SLIDE 160

CODE

... func testAddingAndDeletingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) ... // Master page .verifyMasterPageIsShowing() }

slide-161
SLIDE 161

CODE

... func testAddingAndDeletingEntry() { let zeroLabel = "0" MasterPage(testCase: self) .verifyMasterPageIsShowing() .verifyTableCellCount(is: 0) .tapOnAddButton() .verifyTableCellCount(is: 1) .verifyCell(at: 0, hasLabel: zeroLabel) .tapOnCell(at: 0) ... // Master page .verifyMasterPageIsShowing() .verifyTableCellCount(is: 1) .deleteCell(at: 0) .verifyTableCellCount(is: 0) }

slide-162
SLIDE 162

TIPS & TRICKS

slide-163
SLIDE 163

TIPS & TRICKS

WWDC

2018

Testing Tips & Tricks

🎟

2017

Engineering for Testability

🎟

slide-164
SLIDE 164

TIPS & TRICKS

📽

LOCAL DATA

slide-165
SLIDE 165

TIPS & TRICKS

📽

LOCAL DATA

🚬

AVOID DUPLICATION

slide-166
SLIDE 166

TIPS & TRICKS

📽

LOCAL DATA

🚬

AVOID DUPLICATION

USE MULTIPLE SCHEMES

slide-167
SLIDE 167

GETTING STARTED

slide-168
SLIDE 168

GETTING STARTED

📱

NEXT BUG/ FEATURE

slide-169
SLIDE 169

GETTING STARTED

🔒

IMPORTANT FREQUENT

📱

NEXT BUG/ FEATURE

slide-170
SLIDE 170

GETTING STARTED

🔒

IMPORTANT FREQUENT

IMPORTANT INFREQUENT

📱

NEXT BUG/ FEATURE

slide-171
SLIDE 171

SUMMARY

slide-172
SLIDE 172

SOFTWARE TESTING

AUTOMATED

END-TO-END INTEGRATION UNIT

slide-173
SLIDE 173

UI TESTS

VERIFY BEHAVIOR BUILT ON ACCESSIBILITY RECORD TO LEARN

slide-174
SLIDE 174

TDD

{ } { }

 

slide-175
SLIDE 175

UI TDD

COCOAHEADS • AUG 2018

倫//BSN.DESIGN

TDD