Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Grass on the Other Side - iOS Testing Techn...

The Grass on the Other Side - iOS Testing Techniques

This is a talk at the Google Developer Group in Nuremberg summarizing iOS testing tools, frameworks and techniques for Android developers.

Avatar for xavierLowmiller

xavierLowmiller

April 11, 2019

More Decks by xavierLowmiller

Other Decks in Programming

Transcript

  1. Agenda 1. Why I'm here 2. Unit & Integration Tests

    3. UI Tests 4. Controlling Singletons 5. Snapshot Tests 2
  2. About me • ! iOS developer since 2013, joined adorsys

    2014 • In my free time I • " enjoy bouldering • # host a pub quiz • $ travel a lot • % Programming languages & developer tools • ❤ Swift is my favorite • ✅ Loooove green checkmarks in tests • ( Twitter: @xavierLowmiller 3
  3. Why I'm here I like peeking over the fence. Different

    perspectives make my code better. I hope some of the stuff here makes sense to you. 4
  4. Testing on iOS • Cocoa MVC is more than 20

    years old • Not created with testing in mind • Xcode has really nice support for tests and reports • Testing in the Simulator has a ton of overhead • If you can get away with it, run your tests without a host app 6
  5. Unit Tests • Fast as f*** • Cheap • You

    can never have enough of these • Small amounts of code coverage • White Box 7
  6. 8

  7. func testUnionBetweenSetsShouldContainAllElements() { // Given let set1: Set<Int> = [1,

    2] let set2: Set<Int> = [2, 3] // When let union = set1.union(set2) // Then XCTAssertEqual(union, [1, 2, 3]) } 9
  8. Integration Tests • Are almost as fast • A little

    annoying • Esp. when working with views and windows • Medium amounts of code coverage • White Box 10
  9. func testCancelingShouldShowHintViewControllerBeforeDismissing() { // Given let window = UIWindow() window.rootViewController

    = viewController window.makeKeyAndVisible() // When viewController.cancelButtonTapped() // Then let presented = viewController.presentedViewController as UINavigationController? XCTAssertNotNil(presented) let infoVC = presented ?.topViewController XCTAssert(infoVC is InfoAlertViewController) } 11
  10. UI Tests • Sloooow • XCUITest was introduced in 2014

    • Still a little buggy sometimes • Pretty cool tooling • Often used to implement E2E tests • Fantastic amounts of code coverage • Black Box 12
  11. 13

  12. Tips • Skip all animations • UIView.setAnimationsEnabled(false) • UI Tests

    are built on Accessibility features • Have great Accessibility -> Have great UI Tests 17
  13. How do you test this? func showTodaysDate() -> String {

    let date = Date() return date.formatted() // ... } 19
  14. How do you test this? func showTodaysDate() -> String {

    let date = Date() return date.formatted() // ... } func testShowTodaysDate() { XCAssertEqual(today, "April 11th, 2019") // This test will fail tomorrow ... } 20
  15. func showTodaysDate() -> String { let date = Current.date() return

    date.formatted() // ... } func testShowTodaysDate() { // Given Current.date = { Date(timeIntervalSince1970: 123456) } // When let today = showTodaysDate() // Then XCAssertEqual(today, "January 2nd, 1970") } 22
  16. struct World { var date: () -> Date = Date.init

    } #if DEBUG var Current = World() #else let Current = World() #endif 23
  17. Control the World! • Caches • Authentication • Analytics •

    Persistence • Locale & Calendars • Networking • Singletons 24
  18. More on this • How To Control The World (Talk)

    Stephen Celis, NSSpain 2018 • How To Control The World (Blog Post) Stephen Celis & Brandon Williams, Pointfree.co 25
  19. func testButtonConfiguration() { let button = UIButton.primaryButton XCTAssertEqual(button.backgroundColor, .green) XCTAssertEqual(button.title(for:

    .normal), "Primary Button") XCTAssertEqual(button.titleColor(for: .normal), .white) // ... } This is boring and repetitive 28
  20. import SnapshotTesting func testButtonConfiguration() { let button = UIButton.primaryButton assertSnapshot(matching:

    button, as: .image) } Snapshot Testing checks for every property of a view, even the ones you don't know about. 30
  21. func testNetworkCall() { let request = URLRequest() // ... assertSnapshot(matching:

    request, as: .curl) } curl \ --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOi" \ "https: //example.org/users/234" 36
  22. Input Output Views / View Controllers Image Views / View

    Controllers View Hierarchy URLRequest cURL Request Codable JSON/XML Text Lines Functions with exhaustive input CSV Anything Dump 37
  23. 40