TEST DRIVEN DEVELOPMENT
COMMON CHALLENGES & 

BEST PRACTICES FOR
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
ON IOS
COMMON PITFALLS & BEST PRACTICES FOR TDD
YOUR PRESENTER
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
4/2015~11/2015
12/2015~
1/2014~
WHY TDD?
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
T
D
D Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Question What is TDD?
TEST
DRIVEN
DEVELOPMENTTokyo iOS Meetup June 2016Derek Lee @derekleerock
Question What is TDD?
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
WRITE A TEST
MAKE IT PASS
YADDA YADDA YADDA
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Challenge Getting over the hump
TDD CRASH COURSE
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Challenge Getting over the hump
TESTING WORKFLOW: RED → GREEN → REFACTOR
▸ Write a failing test
▸ Write the simplest implementation
to make it pass
▸ Refactor
▸ Repeat
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
▸ Compiler Errors = Failing Test
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
TESTING WORKFLOW: RED → GREEN → REFACTOR
▸ Red = Failing Test
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
TESTING WORKFLOW: RED → GREEN → REFACTOR
▸ Green = Passing Test
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
TESTING WORKFLOW: RED → GREEN → REFACTOR
TESTING WORKFLOW: RED → GREEN → REFACTOR
▸ Keyboard Shortcuts for improving your test workflow:
▸ ⌘ + 5 → Show the Xcode Test Navigator
▸ ⇧ + ⌘ + U → Compile Tests
▸ ⌘ + U → Run All Tests In Suite
▸ MAGIC + U → Run all tests for current class
▸ MAGIC + G → Re-run last test
* MAGIC = ⌃ + ⌥ + ⌘
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
▸ Setup - Create objects needed to execute the test
▸ Action - Prod the subject (object) under test
▸ Verify - Make assertions about your expectations
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
▸ Override setUp() and tearDown() methods as needed
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
▸ Clearly indicate where the “Act” portion of your test is:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
▸ Use the appropriate assertion for your test expectation
(XCTest)
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
let number = 11
XCTAssertTrue(number == 12)
error: -[MyProjectTests.MyObjectTest testMethod] : XCTAssertTrue
failed -
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
▸ Use the appropriate assertion for your test expectation
(XCTest)
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
let number = 11
XCTAssertEqual(number, 12)
error: -[MyProjectTests.MyObjectTest testMethod] : XCTAssertEqual
failed: ("Optional(11)") is not equal to ("Optional(12)") -
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
▸ XCT Assertion Types
▸ AssertTrue, AssertFalse
▸ AssertEqual, AssertNotEqual (+WithAccuracy)
▸ AssertLessThan, AssertGreaterThan (+OrEqual)
▸ AssertNil, AssertNotNil
▸ AssertThrowsError
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
▸ Nimble (Matcher Framework)
▸ expect(~).to(~) or expect(~).toNot(~)
▸ expect(~).to(beTrue()) or expect(~).to(beFalse())
▸ expect(~).to(beLessThan(~)) // greaterThan…
▸ expect(~).to(beAKindOf(~))
▸ Can also write custom matchers with Nimble
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
GOLDEN RULES OF TDD
▸ Test First
▸ Simplest Solution
▸ Test Once
▸ Test in Isolation
▸ Test the interface, not the implementation
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
TDD BEST PRACTICES
▸ One Failing Test at a Time
▸ Create a Test List
▸ Assert First
▸ Simplest Test Data / Evident Test Data
▸ Avoid conditionals and loops
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
CLASSIC
▸ “Detroit” or “Chicago”
▸ Prefers real objects
▸ Focus: Algorithms
▸ State verification
▸ Test doubles as needed
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
MOCKIST
▸ “London”
▸ Prefers mocks
▸ Focus: Object Interactions
▸ Behavior verification
▸ Test doubles always
GETTING OVER THE HUMP
CONTINUOUS INTEGRATION
▸ Build and test in a clean environment
▸ Automation of your test suite
▸ Test across OSs, simulators, devices
▸ Xcode Server, TeamCity, Travis, CircleCI, Jenkins…
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
CONTINUOUS INTEGRATION - XCODE SERVER BIG SCREEN
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
CONTINUOUS INTEGRATION - PIVOTAL PROJECT MONITOR
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
TAKING THE BLUE PILL
▸ BDD
▸ Clean Architecture
▸ SOLID Principles: SRP, Open/Closed, LSP, ISP, DIP
▸ Don’t Repeat Yourself
▸ Just In Time Design
▸ Refactoring
▸ Continuous Integration
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
GETTING OVER THE HUMP
MY TESTS TAKE
FOREVER TO RUN
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Challenge The Time-Consuming Test Run
THE TIME-CONSUMING TEST RUN
THE USUAL SUSPECTS
▸ Imbalanced Test Suite
▸ Testing Against External Resources
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
TESTING ICE-CREAM CONE ANTI-PATTERN
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
TESTING ICE-CREAM CONE ANTI-PATTERN
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
▸ Brittle
▸ Expensive to write/maintain
▸ Time consuming to run
UI & MANUAL TESTS CAN BE…
TESTING PYRAMID
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
]
]
ARE WE
BUILDING
THE RIGHT
SYSTEM?
ARE WE
BUILDING
THE SYSTEM
RIGHT?
TESTING PYRAMID
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
TIMETOTESTINCREASES
THE TIME-CONSUMING TEST RUN
DESIRED TEST SUITE QUALITIES FOR QUICK TEST FEEDBACK
▸ Few
▸ Fast
▸ Stable
▸ Thorough
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
WHEN TO RUN TESTS
▸ Current Unit/Feature → While building an object / feature
▸ All Units + All Feature → Before commit / push; after
pulling updates from a repo;
▸ Integration, UI → CI Suite
▸ Manual → As needed
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
WHEN TO RUN TESTS
▸ Create a target for each suite of tests that you want to run
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
WHEN TO RUN TESTS
▸ Configure scheme(s) to execute tests:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
WHEN TO RUN TESTS
▸ Use a makefile with xcodebuild (or xctool) to execute the
tests when you need to or from CI:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
units:
@xcodebuild -project Osusume.xcodeproj -scheme "Osusume" -sdk
iphonesimulator -destination "platform=iOS Simulator,OS=9.3,name=
iPhone 6" build test
integration:
@xcodebuild -project Osusume.xcodeproj -scheme "Osusume-Staging"
-sdk iphonesimulator -destination "platform=iOS Simulator,OS=9.3,
name=iPhone 6" build test
THE TIME-CONSUMING TEST RUN
GUIDANCE ON UNIT TESTING - HOW/WHAT TO TEST
▸ Sandi Metz Rails Conf 2013 “The Magic Tricks of Testing”
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
DO MY TESTS HIT EXTERNAL DEPENDENCIES?
▸ Network, REST APIs
▸ Database (includes Core Data!)
▸ File System
▸ External Library or API
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
THEN HOW TO TEST EXTERNAL DEPENDENCIES?
▸ Find the seams where communication occurs
▸ Confirm expected interactions using mock objects
▸ Create an integration test if needed
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE TIME-CONSUMING TEST RUN
GUIDANCE ON MOCK OBJECTS
▸ Martin Fowler, “Mocks Aren’t Stubs”
http://martinfowler.com/articles/mocksArentStubs.html
▸ Uncle Bob, “The Little Mocker” Blog Post
https://blog.8thlight.com/uncle-bob/2014/05/14/
TheLittleMocker.html
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
MY TEST SUITE
FEELS UNSTABLE
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Challenge The Brittle Test Suite
THE BRITTLE TEST SUITE
THE USUAL SUSPECTS
▸ Highly-coupled objects
▸ Long, complicated, or unreadable tests
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE BRITTLE TEST SUITE
HIGHLY COUPLED OBJECTS - DESIGN & ARCHITECTURE
▸ TDD encourages us to write loosely coupled components
that can be easily tested in isolation and combined later.
▸ May need to revisit your architecture
▸ “Build & Swap”
▸ Too difficult or too costly to refactor?
▸ TDD a new component and swap it in
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE BRITTLE TEST SUITE
BUILD & SWAP EXAMPLE #1 - DRUM APP NAVIGATION UX
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE BRITTLE TEST SUITE
BUILD & SWAP EXAMPLE #2 - MIKADO REFACTOR
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
▸ Parse Integration Before:
▸ One single “God” object singleton: ParseHelper.h/.m
▸ Included in 25 other classes
▸ Parse Integration After:
▸ 4 Dependency-Injected Testable “Repository” objects
▸ Can move each repository over as needed
THE BRITTLE TEST SUITE
HOW TDD HELPS
▸ Design
▸ Loosely coupled objects
▸ Well thought out public object APIs
▸ Dev
▸ Gives immediate feedback on quality
▸ Refactoring confidence
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
THE BRITTLE TEST SUITE
HOW TO APPROACH
▸ Practice, practice, practice
▸ Reference Materials
▸ Read “Refactoring: Improving the Design of Existing
Code” (Martin Fowler)
▸ Read “Working Effectively With Legacy Code” (Michael
Feathers)
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
I DON’T KNOW
HOW TO TEST X
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Challenge Fear of the Unknown
FEAR OF THE UNKNOWN
THE USUAL SUSPECTS
▸ What to test - what not to test
▸ How to test specific objects, dependencies, scenarios
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
KNOWING WHAT NOT TO TEST
▸ Private Methods (this is an implementation detail!)
▸ UI Design (fonts, colors, positions, constraints)
▸ Configuration Details (supporting data)
▸ Auto-generated code
▸ Test Fixtures, Test Doubles
▸ Reference: https://blog.8thlight.com/uncle-bob/
2014/04/30/When-tdd-does-not-work.html
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… VIEW CONTROLLERS
▸ Move logic out of MegaController (*Andy Matuschak -
https://realm.io/news/andy-matuschak-refactor-mega-
controller/)
▸ Using Storyboards:
▸ Property Dependency Injection
▸ Without Storyboards:
▸ Constructor Dependency Injection
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… CORE DATA
▸ Use an in-memory Core Data Store
▸ Only setup data needed for test
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… UITABLEVIEW / UICOLLECTIONVIEW
▸ Extract Datasource and/or Delegate to external object for
easier testing
▸ Leverage blocks / closures for common logic
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Swift: Mocks in Swift via Protocols (Blog post, Eli Perkins)
http://blog.eliperkins.me/mocks-in-swift-via-protocols
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
For Objective-C, see OCMock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Find the method definition(s) on the object that you need
to confirm interactions with:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Create your own protocol definition to duplicate the
method you want to confirm interaction with:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Create a fake object (spy) that implements that protocol:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Write your test:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Write the implementation:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
FEAR OF THE UNKNOWN
HOW TO TEST… NSUSERDEFAULTS
▸ Pass in the real object for production code:
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
EASY TO FALL BACK
TO OLD HABITS
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
Challenge Commitment
COMMITMENT
THE USUAL SUSPECTS
▸ Frustration, Fatigue
▸ Cutting corners
▸ Falling back to what is most comfortable
▸ Test last or not testing at all
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
TOOLS YOU’LL NEED
▸ Focus
▸ Patience
▸ Tenacity
▸ Discipline
▸ Dedication
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
COMMITMENT
TIME MANAGEMENT
HOW TO APPROACH
▸ Start Small
▸ 1% each day
▸ Think long-term: Investing in the future of your software
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
REWARDS OF STICKING TO IT
▸ Making forward progress in small increments
▸ Allows refactoring to take place with confidence
▸ Identify bugs early and avoid regressions
▸ Reduces costs up-front
▸ Add new features knowing you won’t break existing ones
▸ Deploy anytime with confidence
▸ Easier to understand code for you and your team
Tokyo iOS Meetup June 2016Derek Lee @derekleerock
COMMITMENT
@DEREKLEEROCK
Thank you!
Tokyo iOS Meetup June 2016Derek Lee @derekleerock

Common Challenges & Best Practices for TDD on iOS

  • 1.
    TEST DRIVEN DEVELOPMENT COMMONCHALLENGES & 
 BEST PRACTICES FOR Tokyo iOS Meetup June 2016Derek Lee @derekleerock ON IOS
  • 2.
    COMMON PITFALLS &BEST PRACTICES FOR TDD YOUR PRESENTER Tokyo iOS Meetup June 2016Derek Lee @derekleerock 4/2015~11/2015 12/2015~ 1/2014~
  • 4.
    WHY TDD? Tokyo iOSMeetup June 2016Derek Lee @derekleerock
  • 5.
    T D D Tokyo iOSMeetup June 2016Derek Lee @derekleerock Question What is TDD?
  • 6.
    TEST DRIVEN DEVELOPMENTTokyo iOS MeetupJune 2016Derek Lee @derekleerock Question What is TDD?
  • 7.
    Tokyo iOS MeetupJune 2016Derek Lee @derekleerock
  • 8.
    WRITE A TEST MAKEIT PASS YADDA YADDA YADDA Tokyo iOS Meetup June 2016Derek Lee @derekleerock Challenge Getting over the hump
  • 9.
    TDD CRASH COURSE TokyoiOS Meetup June 2016Derek Lee @derekleerock Challenge Getting over the hump
  • 10.
    TESTING WORKFLOW: RED→ GREEN → REFACTOR ▸ Write a failing test ▸ Write the simplest implementation to make it pass ▸ Refactor ▸ Repeat Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 11.
    ▸ Compiler Errors= Failing Test Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP TESTING WORKFLOW: RED → GREEN → REFACTOR
  • 12.
    ▸ Red =Failing Test Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP TESTING WORKFLOW: RED → GREEN → REFACTOR
  • 13.
    ▸ Green =Passing Test Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP TESTING WORKFLOW: RED → GREEN → REFACTOR
  • 14.
    TESTING WORKFLOW: RED→ GREEN → REFACTOR ▸ Keyboard Shortcuts for improving your test workflow: ▸ ⌘ + 5 → Show the Xcode Test Navigator ▸ ⇧ + ⌘ + U → Compile Tests ▸ ⌘ + U → Run All Tests In Suite ▸ MAGIC + U → Run all tests for current class ▸ MAGIC + G → Re-run last test * MAGIC = ⌃ + ⌥ + ⌘ Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 15.
    WRITING TESTS TDDSTYLE: ARRANGE → ACT → ASSERT ▸ Setup - Create objects needed to execute the test ▸ Action - Prod the subject (object) under test ▸ Verify - Make assertions about your expectations Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 16.
    WRITING TESTS TDDSTYLE: ARRANGE → ACT → ASSERT ▸ Override setUp() and tearDown() methods as needed Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 17.
    WRITING TESTS TDDSTYLE: ARRANGE → ACT → ASSERT ▸ Clearly indicate where the “Act” portion of your test is: Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 18.
    ▸ Use theappropriate assertion for your test expectation (XCTest) Tokyo iOS Meetup June 2016Derek Lee @derekleerock let number = 11 XCTAssertTrue(number == 12) error: -[MyProjectTests.MyObjectTest testMethod] : XCTAssertTrue failed - GETTING OVER THE HUMP WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
  • 19.
    ▸ Use theappropriate assertion for your test expectation (XCTest) Tokyo iOS Meetup June 2016Derek Lee @derekleerock let number = 11 XCTAssertEqual(number, 12) error: -[MyProjectTests.MyObjectTest testMethod] : XCTAssertEqual failed: ("Optional(11)") is not equal to ("Optional(12)") - GETTING OVER THE HUMP WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
  • 20.
    ▸ XCT AssertionTypes ▸ AssertTrue, AssertFalse ▸ AssertEqual, AssertNotEqual (+WithAccuracy) ▸ AssertLessThan, AssertGreaterThan (+OrEqual) ▸ AssertNil, AssertNotNil ▸ AssertThrowsError Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
  • 21.
    ▸ Nimble (MatcherFramework) ▸ expect(~).to(~) or expect(~).toNot(~) ▸ expect(~).to(beTrue()) or expect(~).to(beFalse()) ▸ expect(~).to(beLessThan(~)) // greaterThan… ▸ expect(~).to(beAKindOf(~)) ▸ Can also write custom matchers with Nimble Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP WRITING TESTS TDD STYLE: ARRANGE → ACT → ASSERT
  • 22.
    GOLDEN RULES OFTDD ▸ Test First ▸ Simplest Solution ▸ Test Once ▸ Test in Isolation ▸ Test the interface, not the implementation Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 23.
    TDD BEST PRACTICES ▸One Failing Test at a Time ▸ Create a Test List ▸ Assert First ▸ Simplest Test Data / Evident Test Data ▸ Avoid conditionals and loops Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 24.
    CLASSIC ▸ “Detroit” or“Chicago” ▸ Prefers real objects ▸ Focus: Algorithms ▸ State verification ▸ Test doubles as needed Tokyo iOS Meetup June 2016Derek Lee @derekleerock MOCKIST ▸ “London” ▸ Prefers mocks ▸ Focus: Object Interactions ▸ Behavior verification ▸ Test doubles always GETTING OVER THE HUMP
  • 25.
    CONTINUOUS INTEGRATION ▸ Buildand test in a clean environment ▸ Automation of your test suite ▸ Test across OSs, simulators, devices ▸ Xcode Server, TeamCity, Travis, CircleCI, Jenkins… Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 26.
    CONTINUOUS INTEGRATION -XCODE SERVER BIG SCREEN Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 27.
    CONTINUOUS INTEGRATION -PIVOTAL PROJECT MONITOR Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 28.
    TAKING THE BLUEPILL ▸ BDD ▸ Clean Architecture ▸ SOLID Principles: SRP, Open/Closed, LSP, ISP, DIP ▸ Don’t Repeat Yourself ▸ Just In Time Design ▸ Refactoring ▸ Continuous Integration Tokyo iOS Meetup June 2016Derek Lee @derekleerock GETTING OVER THE HUMP
  • 29.
    MY TESTS TAKE FOREVERTO RUN Tokyo iOS Meetup June 2016Derek Lee @derekleerock Challenge The Time-Consuming Test Run
  • 30.
    THE TIME-CONSUMING TESTRUN THE USUAL SUSPECTS ▸ Imbalanced Test Suite ▸ Testing Against External Resources Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 31.
    TESTING ICE-CREAM CONEANTI-PATTERN Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 32.
    TESTING ICE-CREAM CONEANTI-PATTERN Tokyo iOS Meetup June 2016Derek Lee @derekleerock ▸ Brittle ▸ Expensive to write/maintain ▸ Time consuming to run UI & MANUAL TESTS CAN BE…
  • 33.
    TESTING PYRAMID Tokyo iOSMeetup June 2016Derek Lee @derekleerock ] ] ARE WE BUILDING THE RIGHT SYSTEM? ARE WE BUILDING THE SYSTEM RIGHT?
  • 34.
    TESTING PYRAMID Tokyo iOSMeetup June 2016Derek Lee @derekleerock TIMETOTESTINCREASES
  • 35.
    THE TIME-CONSUMING TESTRUN DESIRED TEST SUITE QUALITIES FOR QUICK TEST FEEDBACK ▸ Few ▸ Fast ▸ Stable ▸ Thorough Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 36.
    THE TIME-CONSUMING TESTRUN WHEN TO RUN TESTS ▸ Current Unit/Feature → While building an object / feature ▸ All Units + All Feature → Before commit / push; after pulling updates from a repo; ▸ Integration, UI → CI Suite ▸ Manual → As needed Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 37.
    THE TIME-CONSUMING TESTRUN WHEN TO RUN TESTS ▸ Create a target for each suite of tests that you want to run Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 38.
    THE TIME-CONSUMING TESTRUN WHEN TO RUN TESTS ▸ Configure scheme(s) to execute tests: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 39.
    THE TIME-CONSUMING TESTRUN WHEN TO RUN TESTS ▸ Use a makefile with xcodebuild (or xctool) to execute the tests when you need to or from CI: Tokyo iOS Meetup June 2016Derek Lee @derekleerock units: @xcodebuild -project Osusume.xcodeproj -scheme "Osusume" -sdk iphonesimulator -destination "platform=iOS Simulator,OS=9.3,name= iPhone 6" build test integration: @xcodebuild -project Osusume.xcodeproj -scheme "Osusume-Staging" -sdk iphonesimulator -destination "platform=iOS Simulator,OS=9.3, name=iPhone 6" build test
  • 40.
    THE TIME-CONSUMING TESTRUN GUIDANCE ON UNIT TESTING - HOW/WHAT TO TEST ▸ Sandi Metz Rails Conf 2013 “The Magic Tricks of Testing” Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 41.
    THE TIME-CONSUMING TESTRUN DO MY TESTS HIT EXTERNAL DEPENDENCIES? ▸ Network, REST APIs ▸ Database (includes Core Data!) ▸ File System ▸ External Library or API Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 42.
    THE TIME-CONSUMING TESTRUN THEN HOW TO TEST EXTERNAL DEPENDENCIES? ▸ Find the seams where communication occurs ▸ Confirm expected interactions using mock objects ▸ Create an integration test if needed Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 43.
    THE TIME-CONSUMING TESTRUN GUIDANCE ON MOCK OBJECTS ▸ Martin Fowler, “Mocks Aren’t Stubs” http://martinfowler.com/articles/mocksArentStubs.html ▸ Uncle Bob, “The Little Mocker” Blog Post https://blog.8thlight.com/uncle-bob/2014/05/14/ TheLittleMocker.html Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 44.
    MY TEST SUITE FEELSUNSTABLE Tokyo iOS Meetup June 2016Derek Lee @derekleerock Challenge The Brittle Test Suite
  • 45.
    THE BRITTLE TESTSUITE THE USUAL SUSPECTS ▸ Highly-coupled objects ▸ Long, complicated, or unreadable tests Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 46.
    THE BRITTLE TESTSUITE HIGHLY COUPLED OBJECTS - DESIGN & ARCHITECTURE ▸ TDD encourages us to write loosely coupled components that can be easily tested in isolation and combined later. ▸ May need to revisit your architecture ▸ “Build & Swap” ▸ Too difficult or too costly to refactor? ▸ TDD a new component and swap it in Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 47.
    THE BRITTLE TESTSUITE BUILD & SWAP EXAMPLE #1 - DRUM APP NAVIGATION UX Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 48.
    THE BRITTLE TESTSUITE BUILD & SWAP EXAMPLE #2 - MIKADO REFACTOR Tokyo iOS Meetup June 2016Derek Lee @derekleerock ▸ Parse Integration Before: ▸ One single “God” object singleton: ParseHelper.h/.m ▸ Included in 25 other classes ▸ Parse Integration After: ▸ 4 Dependency-Injected Testable “Repository” objects ▸ Can move each repository over as needed
  • 49.
    THE BRITTLE TESTSUITE HOW TDD HELPS ▸ Design ▸ Loosely coupled objects ▸ Well thought out public object APIs ▸ Dev ▸ Gives immediate feedback on quality ▸ Refactoring confidence Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 50.
    THE BRITTLE TESTSUITE HOW TO APPROACH ▸ Practice, practice, practice ▸ Reference Materials ▸ Read “Refactoring: Improving the Design of Existing Code” (Martin Fowler) ▸ Read “Working Effectively With Legacy Code” (Michael Feathers) Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 51.
    I DON’T KNOW HOWTO TEST X Tokyo iOS Meetup June 2016Derek Lee @derekleerock Challenge Fear of the Unknown
  • 52.
    FEAR OF THEUNKNOWN THE USUAL SUSPECTS ▸ What to test - what not to test ▸ How to test specific objects, dependencies, scenarios Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 53.
    FEAR OF THEUNKNOWN KNOWING WHAT NOT TO TEST ▸ Private Methods (this is an implementation detail!) ▸ UI Design (fonts, colors, positions, constraints) ▸ Configuration Details (supporting data) ▸ Auto-generated code ▸ Test Fixtures, Test Doubles ▸ Reference: https://blog.8thlight.com/uncle-bob/ 2014/04/30/When-tdd-does-not-work.html Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 54.
    FEAR OF THEUNKNOWN HOW TO TEST… VIEW CONTROLLERS ▸ Move logic out of MegaController (*Andy Matuschak - https://realm.io/news/andy-matuschak-refactor-mega- controller/) ▸ Using Storyboards: ▸ Property Dependency Injection ▸ Without Storyboards: ▸ Constructor Dependency Injection Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 55.
    FEAR OF THEUNKNOWN HOW TO TEST… CORE DATA ▸ Use an in-memory Core Data Store ▸ Only setup data needed for test Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 56.
    FEAR OF THEUNKNOWN HOW TO TEST… UITABLEVIEW / UICOLLECTIONVIEW ▸ Extract Datasource and/or Delegate to external object for easier testing ▸ Leverage blocks / closures for common logic Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 57.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Swift: Mocks in Swift via Protocols (Blog post, Eli Perkins) http://blog.eliperkins.me/mocks-in-swift-via-protocols Tokyo iOS Meetup June 2016Derek Lee @derekleerock For Objective-C, see OCMock
  • 58.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Find the method definition(s) on the object that you need to confirm interactions with: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 59.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Create your own protocol definition to duplicate the method you want to confirm interaction with: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 60.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Create a fake object (spy) that implements that protocol: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 61.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Write your test: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 62.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Write the implementation: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 63.
    FEAR OF THEUNKNOWN HOW TO TEST… NSUSERDEFAULTS ▸ Pass in the real object for production code: Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 64.
    EASY TO FALLBACK TO OLD HABITS Tokyo iOS Meetup June 2016Derek Lee @derekleerock Challenge Commitment
  • 65.
    COMMITMENT THE USUAL SUSPECTS ▸Frustration, Fatigue ▸ Cutting corners ▸ Falling back to what is most comfortable ▸ Test last or not testing at all Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 66.
    TOOLS YOU’LL NEED ▸Focus ▸ Patience ▸ Tenacity ▸ Discipline ▸ Dedication Tokyo iOS Meetup June 2016Derek Lee @derekleerock COMMITMENT
  • 67.
    TIME MANAGEMENT HOW TOAPPROACH ▸ Start Small ▸ 1% each day ▸ Think long-term: Investing in the future of your software Tokyo iOS Meetup June 2016Derek Lee @derekleerock
  • 68.
    REWARDS OF STICKINGTO IT ▸ Making forward progress in small increments ▸ Allows refactoring to take place with confidence ▸ Identify bugs early and avoid regressions ▸ Reduces costs up-front ▸ Add new features knowing you won’t break existing ones ▸ Deploy anytime with confidence ▸ Easier to understand code for you and your team Tokyo iOS Meetup June 2016Derek Lee @derekleerock COMMITMENT
  • 70.
    @DEREKLEEROCK Thank you! Tokyo iOSMeetup June 2016Derek Lee @derekleerock