# Compose UI Testing Patterns

Use when writing or reviewing Jetpack Compose UI tests, screenshot tests or...

- Repository: https://github.com/chrisbanes/skills (1135 stars)
- Category: Design
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add chrisbanes/skills --skill compose-ui-testing-patterns -g -a claude-code -y`
Codex: `npx skills add chrisbanes/skills --skill compose-ui-testing-patterns -g -a codex -y`
Cursor: `npx skills add chrisbanes/skills --skill compose-ui-testing-patterns -g -a cursor -y`
Gemini CLI: `npx skills add chrisbanes/skills --skill compose-ui-testing-patterns -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add chrisbanes/skills`

## Description

Use when writing or reviewing Jetpack Compose UI tests, screenshot tests or baseline-recording evidence, previews, semantics assertions, fake image loading, keyboard input, focus assertions, interaction state (hover/pressed/focused), or tests for plain state-driven UI composables.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Compose: UI testing patterns

## Core principle

Test the smallest UI contract that proves the behavior. Prefer plain state-driven UI tests with callbacks. Add integration only when lifecycle, navigation, DI, or platform behavior is the thing under test.

## Procedure

1. State the behavior and test concern the task asks you to prove.
2. Inspect the existing test against that concern and choose the smallest
   sufficient seam from the table below.
3. Keep focused edits within the requested test concern. Do not move test-only
   helpers into production or broaden production APIs unless that production
   boundary is itself under test.
4. Drive controlled state or input, synchronize through Compose when needed,
   and assert an observable semantic, visual, or callback result.
5. Finish with no edit when the existing test already uses the narrowest valid
   seam and proves the requested behavior.

## Test target choice

| What you need to prove | Test shape |
|---|---|
| Text, button, loading/error branch, conditional content | Plain UI Compose test |
| Callback wiring from click/input | Plain UI Compose test |
| Focus navigation or keyboard behavior | Compose test with key input |
| Visual layout, clipping, elevation, typography, image composition | Screenshot test |
| State holder updates UI correctly | State holder/unit test plus one wiring smoke test |
| Hover, pressed, focused, dragged interaction state | Plain UI test with MutableInteractionSource |
| Navigation, lifecycle, DI integration | Integration test |

## Prefer plain UI tests

If the screen has a state holder/UI split, test the plain UI composable:

```kotlin
composeTestRule.setContent {
    ProfileScreen(
        state = ProfileUiState(name = "Ada", canSave = true),
        onNameChange = {},
        onSaveClick = { saved = true },
        onBackClick = {},
    )
}

composeTestRule.onNodeWithText("Ada").assertIsDisplayed()
composeTestRule.onNodeWithText("Save").performClick()

The rest: https://github.com/chrisbanes/skills/blob/HEAD/skills/compose-ui-testing-patterns/SKILL.md
