Chapter 1: Why Modern Android Testing Is Different
- 1.1 The Pyramid We Inherited
- 1.2 Why the Pyramid’s Assumptions Don’t Hold on Modern Android
- 1.3 The Testing Trophy
- 1.4 Confidence Per Millisecond
- 1.5 Implementation Detail Versus Behavior
- 1.6 What “Modern” Actually Means
- 1.7 Common Misconceptions
- 1.8 How This Book Is Organized
- Key Takeaways
- What’s Next
Chapter 2: The Testing Landscape
- 2.1 A Vocabulary Problem
- 2.2 The Five Categories
- 2.3 The Boundaries Are Fuzzy — On Purpose
- 2.4 A Decision Framework
- 2.5 One Feature, Five Ways
- 2.6 Anti-Patterns
- Key Takeaways
- What’s Next
Chapter 3: Setting Up a Testable Project
- 3.1 Meet Perch
- 3.2 Source Sets: Where Tests Live
- 3.3 The Gradle Setup
- 3.4 JUnit 4 or JUnit 5
- 3.5 Running on the JVM Versus a Device
- 3.6 A First Green Across the Board
- 3.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 4: Anatomy of a Good Test
- 4.1 A Test Is Read Far More Often Than It’s Written
- 4.2 Naming: A Failure Should Read Like a Sentence
- 4.3 Structure: Arrange, Act, Assert
- 4.4 One Reason to Fail
- 4.5 Readable Failures
- 4.6 The FIRST Properties
- 4.7 A Good Test, Fully Assembled
- 4.8 Pitfalls
- Key Takeaways
- What’s Next
Chapter 5: Test Doubles Explained
- 5.1 A Vocabulary for Stand-Ins
- 5.2 The Doubles, Concretely
- 5.3 Why Fakes Usually Win
- 5.4 When Mocks and Stubs Are Right
- 5.5 MockK, Properly
- 5.6 Building Fakes That Earn Their Keep
- 5.7 A Decision Guide
- 5.8 Pitfalls
- Key Takeaways
- What’s Next
Chapter 6: Assertion Libraries
- 6.1 Why the Built-In Assertions Aren’t Enough
- 6.2 The Three Contenders
- 6.3 Soft Assertions
- 6.4 Asserting on Exceptions
- 6.5 Custom Subjects for Domain Types
- 6.6 The House Pick
- 6.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 7: Testing Pure Kotlin and Domain Logic
- 7.1 The Easiest, Highest-Return Tests
- 7.2 Testing at the Boundaries
- 7.3 Purity as a Testability Strategy
- 7.4 Value Objects: Test the Logic, Not the Compiler
- 7.5 Mappers and Round-Trips
- 7.6 A Map of the Domain Layer
- 7.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 8: Testing Use Cases and Repositories with Fakes
- 8.1 Testing a Use Case
- 8.2 Where Interaction Verification Earns Its Place
- 8.3 Testing an Offline-First Repository
- 8.4 A Repository Behavior Checklist
- 8.5 Pitfalls
- Key Takeaways
- What’s Next
Chapter 9: Parameterized and Data-Driven Tests
- 9.1 When to Parameterize (and When Not To)
- 9.2 JUnit 4: Functional but Clunky
- 9.3 JUnit 5: The Reason the Carve-Out Exists
- 9.4 Kotest’s Data-Driven DSL
- 9.5 The Pragmatic Default: Table-Driven Kotlin
- 9.6 Choosing an Approach
- 9.7 A Note Toward Property-Based Testing
- 9.8 Pitfalls
- Key Takeaways
- What’s Next
Chapter 10: Testing Coroutines
- 10.1 Why Coroutines Need Special Testing
- 10.2
runTestand Virtual Time - 10.3 The Two Test Dispatchers
- 10.4 The
Dispatchers.MainProblem - 10.5 The
runTestScheduler Versus the Main Dispatcher - 10.6 Testing Exceptions and Cancellation
- 10.7 Comparison and Quick Reference
- 10.8 Pitfalls
- Key Takeaways
- What’s Next
Chapter 11: Injecting Dispatchers for Testability
- 11.1 Why Hardcoded Dispatchers Break Tests
- 11.2 The Dispatcher-Provider Pattern
- 11.3 Injecting Dispatchers with Hilt
- 11.4 Choosing an Injection Style
- 11.5 What Not to Inject
- 11.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 12: Testing Flows with Turbine
- 12.1 The Basic Shape
- 12.2 Terminal Events: Completion and Error
- 12.3 Testing Operators and Transformations
- 12.4 Testing Several Flows at Once
- 12.5 A Note on Hot Flows
- 12.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 13: Testing StateFlow and SharedFlow
- 13.1 Hot Versus Cold, and Why It Matters
- 13.2 The Conflation Trap
- 13.3 The
WhileSubscribedSubscription Gotcha - 13.4
SharedFlowand One-Shot Events - 13.5 Hot-Flow Testing at a Glance
- 13.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 14: Testing ViewModels End to State
- 14.1 The Standard Setup
- 14.2 Driving the State Machine
- 14.3 Actions, Loading, and Errors
- 14.4 One-Shot Events
- 14.5 SavedStateHandle
- 14.6 Structuring for Readability
- 14.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 15: Compose Testing Fundamentals
- 15.1 The Test Rule and
setContent - 15.2 The Semantics Tree
- 15.3 Finders
- 15.4 Actions
- 15.5 Assertions
- 15.6 The Same API in Both Homes
- 15.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 16: Semantics and Accessibility as a Testing Contract
- 16.1 What the Semantics Tree Is
- 16.2 Merged Versus Unmerged Trees
- 16.3 Adding Semantics Deliberately
- 16.4 Custom Semantics Properties
- 16.5
testTagsAsResourceIdand the Honest Use of Tags - 16.6 The Contract Restated
- 16.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 17: Testing State, Recomposition, and Side Effects
- 17.1 Hoisted State Is Testable State
- 17.2 Testing That the UI Reacts to State
- 17.3 Testing Side Effects
- 17.4 Surviving Recomposition and Configuration Changes
- 17.5 A Note on Recomposition Counts
- 17.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 18: Synchronization and Idling
- 18.1 How Auto-Synchronization Works
- 18.2 When Auto-Sync Isn’t Enough
- 18.3 Taking Control of the Clock
- 18.4 Idling Resources for External Async
- 18.5 Synchronization Tools at a Glance
- 18.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 19: Testing Navigation
- 19.1 Two Levels of Navigation Testing
- 19.2 Testing Classic Navigation Compose
- 19.3 Testing Navigation 3
- 19.4 Testing Deep Links
- 19.5 Where Navigation Tests Belong
- 19.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 20: Testing Compose Screens with Hilt
- 20.1 Why Plain Construction Usually Wins
- 20.2 When Hilt in Tests Earns Its Cost
- 20.3 The Setup: Runner, Application, Rules
- 20.4 Substituting Fakes Two Ways
- 20.5 Hilt Tests Under Robolectric
- 20.6 A Decision Guide
- 20.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 21: The Robot Pattern for Readable UI Tests
- 21.1 The Problem, Concretely
- 21.2 A Robot
- 21.3 A Kotlin DSL Flavor
- 21.4 Composing Robots for Flows
- 21.5 Keeping Robots Honest
- 21.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 22: Why Screenshot Testing
- 22.1 The Bugs Semantic Tests Can’t See
- 22.2 How Screenshot Testing Works
- 22.3 What It Proves, and What It Doesn’t
- 22.4 When It’s Worth the Cost
- 22.5 The Landscape Ahead
- 22.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 23: Paparazzi
- 23.1 How Paparazzi Works
- 23.2 Setup
- 23.3 Recording and Verifying
- 23.4 Capturing Across Configurations
- 23.5 Determinism: The Fixed-Clock Discipline
- 23.6 Strengths and Limits
- 23.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 24: Roborazzi
- 24.1 How Roborazzi Works
- 24.2 Setup
- 24.3 The Differentiator: Capturing Interaction States
- 24.4 Recording and Verifying
- 24.5 Strengths and Limits
- 24.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 25: Compose Preview Screenshot Testing
- 25.1 The Idea: Previews You Already Have
- 25.2 Setup
- 25.3 Recording and Verifying
- 25.4 Multipreview: Configuration for Free
- 25.5 Strengths and Limits
- 25.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 26: Paparazzi vs. Roborazzi vs. Preview Screenshot Testing
- 26.1 The Decision Table
- 26.2 Choosing by Scenario
- 26.3 Combining Tools
- 26.4 This Book’s Stance
- 26.5 Pitfalls
- Key Takeaways
- What’s Next
Chapter 27: Testing Across Configurations
- 27.1 The Configuration Matrix
- 27.2 Expressing the Matrix with Multipreview
- 27.3 Expressing the Matrix with Parameterization
- 27.4 RTL and Long Text: The Undertested Cases
- 27.5 Avoiding the Combinatorial Explosion
- 27.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 28: Managing Golden Images
- 28.1 The Record–Review–Verify Workflow
- 28.2 The Determinism Problem
- 28.3 Tolerance Thresholds
- 28.4 Storage and Repository Health
- 28.5 The Review Experience
- 28.6 Preventing Rot
- 28.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 29: Testing Room and Migrations
- 29.1 Why Test the Real DAO
- 29.2 In-Memory Database Tests
- 29.3 What’s Worth Testing in a DAO
- 29.4 Migrations: The Highest-Stakes Test
- 29.5 Robolectric Versus Instrumented for Room
- 29.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 30: Testing DataStore and Preferences
- 30.1 The Layering, Restated
- 30.2 Testing a Preferences DataStore
- 30.3 The One-Instance-Per-File Rule
- 30.4 Proto DataStore
- 30.5 Testing SharedPreferences Migration
- 30.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 31: Network Testing with MockWebServer
- 31.1 What MockWebServer Is
- 31.2 Setup and a Successful Response
- 31.3 Testing Error Handling
- 31.4 Asserting the Request You Sent
- 31.5 Ktor’s MockEngine
- 31.6 Where This Fits
- 31.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 32: Testing WorkManager
- 32.1 Two Levels of WorkManager Testing
- 32.2 Testing Worker Logic
- 32.3 Testing Scheduling and Constraints
- 32.4 Robolectric Versus Instrumented
- 32.5 Pitfalls
- Key Takeaways
- What’s Next
Chapter 33: Espresso and View Interop
- 33.1 Espresso in One Paragraph
- 33.2 The Interop Point
- 33.3 Testing Views Inside Compose and Compose Inside Views
- 33.4 Espresso Intents for Navigation to Other Activities
- 33.5 The Migration Perspective
- 33.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 34: Designing an E2E Strategy
- 34.1 The Cost Profile
- 34.2 What Belongs at E2E
- 34.3 The Ice-Cream Cone, Revisited
- 34.4 Hermetic Versus Real-Backend E2E
- 34.5 The Two Tools Ahead
- 34.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 35: Full User Journeys with Compose
- 35.1 The Hermetic Setup
- 35.2 Composing Robots into a Journey
- 35.3 Test Tags for Journey Stability
- 35.4 Synchronization Across a Long Journey
- 35.5 State Between Tests
- 35.6 In-Process Versus Out-of-Process
- 35.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 36: Maestro
- 36.1 What Maestro Is and Why It’s Different
- 36.2 A First Flow
- 36.3 Resilience: The Selling Point
- 36.4 Reusable Sub-Flows
- 36.5 The Hermetic Challenge
- 36.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 37: Running E2E at Scale
- 37.1 Why a Device Matrix
- 37.2 Gradle Managed Devices
- 37.3 Firebase Test Lab
- 37.4 Sharding
- 37.5 Choosing a Representative Matrix
- 37.6 Flakiness and Triage at Scale
- 37.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 38: Test-Driven Development in a Compose Codebase
- 38.1 The Cycle
- 38.2 A Worked Example
- 38.3 Where TDD Shines
- 38.4 Where Test-First Is Awkward
- 38.5 TDD’s Real Payoff: Design
- 38.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 39: Fighting Flakiness
- 39.1 The Taxonomy of Causes
- 39.2 Diagnosing a Flaky Test
- 39.3 Fixing by Cause
- 39.4 The Retry Trap
- 39.5 Quarantine: The Right Middle Ground
- 39.6 The Culture
- 39.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 40: Coverage That Means Something
- 40.1 What Coverage Actually Measures
- 40.2 Why Chasing the Number Backfires
- 40.3 What Coverage Is Genuinely Good For
- 40.4 Setting Up Kover
- 40.5 Coverage in CI: Gate Carefully
- 40.6 Mutation Testing: Measuring What Coverage Can’t
- 40.7 What to Actually Target
- 40.8 Pitfalls
- Key Takeaways
- What’s Next
Chapter 41: Fast Feedback
- 41.1 Where Slowness Comes From
- 41.2 Parallelization
- 41.3 Sharding
- 41.4 Module Boundaries and Test Impact
- 41.5 Caching
- 41.6 Tiered Feedback Loops
- 41.7 Optimizing the Slow Tail
- 41.8 Pitfalls
- Key Takeaways
- What’s Next
Chapter 42: Wiring It All into CI/CD
- 42.1 The Staged Pipeline
- 42.2 A Concrete Pipeline
- 42.3 Gates: Fast and Trustworthy or Ignored
- 42.4 Surfacing Results Where Developers Look
- 42.5 Caching and Speed in CI
- 42.6 Branch Protection and Flaky Handling
- 42.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 43: Property-Based Testing with Kotest
- 43.1 From Examples to Properties
- 43.2 A First Property
- 43.3 The Round-Trip Property
- 43.4 Shrinking: The Killer Feature
- 43.5 What Makes a Good Property
- 43.6 Where It Fits in Perch
- 43.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 44: Testing Multi-Module Projects
- 44.1 Why Modules Help Testing
- 44.2 Sharing Test Code with
test-fixtures - 44.3 Contract Tests: Keeping Fakes Honest
- 44.4 Convention Plugins for Test Setup
- 44.5 Where Cross-Module Integration Is Tested
- 44.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 45: Testing Shared KMP/CMP Code
- 45.1 The Source-Set Model
- 45.2 The Multiplatform Test Toolkit
- 45.3 Testing
expect/actual - 45.4 Compose Multiplatform UI Testing
- 45.5 Running Tests Per Target
- 45.6 The Bridge to Perch
- 45.7 Pitfalls
- Key Takeaways
- What’s Next
Chapter 46: Performance Testing
- 46.1 What to Measure
- 46.2 Macrobenchmark
- 46.3 Baseline Profiles
- 46.4 The Determinism Problem, Again
- 46.5 Performance in CI
- 46.6 Pitfalls
- Key Takeaways
- What’s Next
Chapter 47: Accessibility Testing as a First-Class Concern
- 47.1 Why First-Class
- 47.2 What to Test
- 47.3 Automated Accessibility Checks
- 47.4 What Automation Can’t Catch
- 47.5 Weaving It Into the Suite
- 47.6 Pitfalls
- 47.7 Key Takeaways
- Closing: Testing as Serving Users
