iOS Unit Testing by Example

Book description

Fearlessly change the design of your iOS code with solid unit tests. Use Xcode's built-in test framework XCTest and Swift to get rapid feedback on all your code - including legacy code. Learn the tricks and techniques of testing all iOS code, especially view controllers (UIViewControllers), which are critical to iOS apps. Learn to isolate and replace dependencies in legacy code written without tests. Practice safe refactoring that makes these tests possible, and watch all your changes get verified quickly and automatically. Make even the boldest code changes with complete confidence.

Manual code and UI testing get slower the deeper your navigation hierarchy goes. It can take several taps just to reach a particular screen, never mind the actual workflow tests. Automatic unit testing offers such rapid feedback that it can change the rules of development. Bring testing to iOS development, even for legacy code. Use XCTest to write unit tests in Swift for all your code.

iOS developers typically reserve unit tests for their model classes alone. But that approach skips most of the code common to iOS apps, especially with UIViewControllers. Learn how to unit test these view controllers to expand your unit testing possibilities. Since good unit tests form the bedrock for safe refactoring, you're empowered to make bold changes. Learn how to avoid the most common mistakes Swift programmers make with the XCTest framework. Use code coverage to find holes in your test suites. Learn how to identify hard dependencies.

Reshape the design of your code quickly, with less risk and less fear.

Publisher resources

View/Submit Errata

Table of contents

  1.  Foreword
  2.  Preface
    1. How This Book Is Organized
    2. Disclaimer: No SwiftUI Support
    3. Online Resources
    4. Acknowledgments
  3. Part I. Foundations
    1. 1. Assert Yourself
      1. What Are Unit Tests Anyway?
      2. Create a Place to Play with Tests
      3. Write Your First Assertion
      4. Add a Descriptive Message
      5. Avoid Conditionals in Tests
      6. Describe Objects upon Failure
      7. Test for Equality
      8. Test Equality with Optionals
      9. Fudge Equality with Doubles and Floats
      10. Avoid Redundant Messages
      11. Choose the Right Assertion
      12. Key Takeaways
      13. Activities
      14. What’s Next?
    2. 2. Manage Your Test Life Cycles
      1. Make a New Place to Play
      2. Start from Test Zero
      3. Hook Up Tests to Production Code
      4. Examine Console Output
      5. Observe Object Life Cycles to Learn the Phases of a Test
      6. The Wrong Way to Reduce Duplicate Test Code
      7. Learn How XCTest Manages Test Cases
      8. Use setUp() and tearDown()
      9. Key Takeaways
      10. Activities
      11. What’s Next?
    3. 3. Measure Code Coverage and Add Tests
      1. Make a New Place to Play
      2. Enable Code Coverage
      3. Examine Code Coverage Results
      4. Drill into a Partially Covered Line
      5. Add Tests for Existing Code
      6. Cover a Conditional
      7. Cover a Loop
      8. Cover Statements in a Sequence
      9. Avoid Percentage Targets, Embrace Forward Movement
      10. Key Takeaways
      11. Activities
      12. What’s Next?
    4. 4. Take Control of Application Launch
      1. Make a New Place to Play
      2. Observe the Default Behavior
      3. Learn About the Test Launch Sequence
      4. Bypass the Normal App Delegate
      5. Put Up with the Initial View Controller
      6. Tweak Your Testing App Delegate
      7. Key Takeaways
      8. Activities
      9. What’s Next?
    5. 5. Load View Controllers
      1. Make a New Place to Play
      2. Set Up a Storyboard-Based View Controller for Experiments
      3. Load a Storyboard-Based View Controller
      4. Set Up a XIB-Based View Controller for Experiments
      5. Load a XIB-Based View Controller
      6. Set Up a Code-Based View Controller for Experiments
      7. Load a Code-Based View Controller
      8. Key Takeaways
      9. Activities
      10. What’s Next?
    6. 6. Manage Difficult Dependencies
      1. Be Okay with Problem-Free Dependencies
      2. Identify Difficult Dependencies
      3. Create Boundaries to Isolate Dependencies
      4. Make a New Place to Play
      5. Add Backdoors to Singletons You Own
      6. Subclass and Override: A Legacy Code Technique
      7. Inject Instances Through Initializers or Properties
      8. Inject Closures to Make New Instances
      9. Key Takeaways
      10. Activities
      11. What’s Next?
  4. Part II. iOS Testing Tips and Techniques
    1. 7. Testing Outlet Connections
      1. Make a New Place to Play
      2. Test Outlet Connections
      3. Check the Effectiveness of Failure Messages
      4. Key Takeaways
      5. Activities
      6. What’s Next?
    2. 8. Testing Button Taps (Using Actions)
      1. Make a Place to Play with a Button
      2. Test Button Taps
      3. Make a Test Helper for Button Taps
      4. Key Takeaways
      5. Activities
      6. What’s Next?
    3. 9. Testing Alerts
      1. Make a New Place to Play
      2. Add the Helper Framework to the Project
      3. Test Alerts Using the Alert Verifier
      4. Move the SUT into the Test Fixture
      5. Add Tests for Alert Buttons
      6. Key Takeaways
      7. Activities
      8. What’s Next?
    4. 10. Testing Navigation Between Screens
      1. Make a New Place to Play
      2. Set Up Code-Based Navigation
      3. Set Up Segue-Based Navigation
      4. Test Code-Based Push Navigation
      5. Test Code-Based Modal Presentation
      6. Test Segue-Based Push Navigation
      7. Test Segue-Based Modal Navigation
      8. Key Takeaways
      9. Activities
      10. What’s Next?
    5. 11. Testing UserDefaults (with Fakes)
      1. Make a New Place to Play
      2. Isolate UserDefaults with Dependency Injection
      3. Extract a Protocol to Support Test Doubles
      4. Make a Fake Object
      5. Test UserDefaults
      6. Key Takeaways
      7. Activities
      8. What’s Next?
    6. 12. Testing Network Requests (with Mocks)
      1. Make a New Place to Play
      2. Isolate URLSession with Dependency Injection
      3. Extract a URLSession Protocol for Test Doubles
      4. Make a Test Spy
      5. Design the Test Case
      6. Promote the Test Spy into a Mock Object
      7. Improve Mock Object Reporting
      8. Key Takeaways
      9. Activities
      10. What’s Next?
    7. 13. Testing Network Responses (and Closures)
      1. Make a New Place to Play
      2. Parse the Response
      3. Start with a Fresh Test Spy
      4. Design the Test Case
      5. Test Asynchronous Code
      6. Keep Asynchronous Code in Its Closure
      7. Test an Error Scenario
      8. Key Takeaways
      9. Activities
      10. What’s Next?
    8. 14. Testing Text Fields (and Delegate Methods)
      1. Make a Place to Play
      2. Test the Outlets
      3. Test Attributes and Wrangle UIKit Descriptions
      4. Test Delegate Methods
      5. Test Input Focus
      6. Key Takeaways
      7. Activities
      8. What’s Next?
    9. 15. Testing Table Views
      1. Make a Place to Play
      2. Test Table Views
      3. Key Takeaways
      4. Activities
      5. What’s Next?
    10. 16. Testing View Appearance (with Snapshots)
      1. Make a Place to Play
      2. Add FBSnapshotTestCase to a Test Target
      3. Set the Location for Reference Images
      4. Write a Snapshot Test
      5. See the Difference in a Snapshot Failure
      6. Manage Your Snapshot Tests
      7. Key Takeaways
      8. Activities
      9. What’s Next?
  5. Part III. Using Your New Power
    1. 17. Unleash the Power of Refactoring
      1. What Is Refactoring?
      2. Lay Out the Views for Our Practice App
      3. Add the Code to Our Practice App
      4. Replace the Difficult Dependency with a Mock Object
      5. Write the First Tests of the Change Password View Controller
      6. Test the Cancel Button
      7. Test the Submit Button
      8. Test the Text Field Delegate Method
      9. Refactor to Break Up a Long Function
      10. Extract a Method with Parameters
      11. Clean Up a Few More Places
      12. Key Takeaways
      13. What’s Next?
    2. 18. Refactoring: Moving to MVVM
      1. What Is MVVM?
      2. Replace String Literals to Use a View Model
      3. Overwrite Storyboard Labels
      4. Respond to Changes in the View Model
      5. Move Logic into the View Model
      6. Key Takeaways
      7. What’s Next?
    3. 19. Refactoring: Moving to MVP
      1. What Is MVP?
      2. Set Up the MVP Types
      3. Extract Methods into the View Commands Protocol
      4. Move a Function into the Presenter
      5. Remove the didSet Observer
      6. Use Refactoring Principles to Reparent a Swift Type
      7. Move Several Functions to the Presenter
      8. Extract Password Validation into Its Own Type
      9. Finish Up the Refactoring to MVP
      10. Key Takeaways
      11. What’s Next?
    4. 20. Test-Driven Development Beckons to You
      1. What Is TDD?
      2. Make a New Place to Play with TDD
      3. Define the Requirements of the Time-of-Day Greeter
      4. Design the First Failing Test with Bare Production Code
      5. Make the First Test Pass with “Good Morning”
      6. Refactor the First Test to Make It More Expressive
      7. Repeat the TDD Steps for the Second Test
      8. Add Tests to Expand “Good Afternoon”
      9. Implement “Good Evening”
      10. Step Back to Refactor the Method as a Whole
      11. Add the Name to the Greeting
      12. Key Takeaways
      13. What’s Next?
  6.  Bibliography

Product information

  • Title: iOS Unit Testing by Example
  • Author(s): Jon Reid
  • Release date: June 2020
  • Publisher(s): Pragmatic Bookshelf
  • ISBN: 9781680506815