agentleFS
wrinfotelwrinfotel/verified-android-skills/skills/compose-testing/SKILL.md

compose-testing

Skill0 starsChanged 32 days agoMITView on GitHub

Jetpack Compose testing discipline: test-rule choice, synchronization without sleeps, ui-test dependencies, and semantics-based assertions. Use when writing or reviewing Compose UI tests. Core rules have machine checks in checks/.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    After ANY Compose test edit, run the Verification step (bottom of this file).

    line 14
  2. Very specific:

    MUST NOT block the test thread (Thread.sleep, SystemClock.sleep, delay) to "wait for the UI".

    line 19
  3. Very specific:

    MUST drive mainClock instead of sleeping through animations:

    line 45
  4. Very specific:

    MUST NOT gate tests on external blocking (CountDownLatch) where a waitUntil API fits — external blocking does not advance the test clock.

    line 58
  5. Very specific:

    MUST use createComposeRule() for pure composable content and createAndroidComposeRule<Activity>() when the test needs the Activity.

    line 63
  6. Very specific:

    MUST NOT pair ActivityScenarioRule (or a manually launched activity) with a ComposeTestRule — the activity is then launched twice, a …

    line 65
  7. Distinctive:

    MUST declare, in the module holding the UI tests:

    line 82
  8. Very specific:

    MUST find nodes through semantics: onNodeWithText / onNodeWithTag / onNodeWithContentDescription, and assert visibility with …

    line 95
  9. Distinctive:

    Run after every Compose test edit (from the project root):

    line 118
  10. Distinctive:

    All three must pass (exit 0) before declaring the task done.

    line 126

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Compose Testing

Operational rules for a coding agent. RIGHT/WRONG pairs are canonical. After ANY Compose test edit, run the Verification step (bottom of this file).

1. Synchronization — never block, drive the clock

MUST NOT block the test thread (Thread.sleep, SystemClock.sleep, delay) to "wait for the UI". Compose tests run on a virtual clock: assertions and actions auto-synchronize on idle. For conditions the clock cannot see (external data loading, non-Compose measure/draw) use waitUntil and its helpers; for animations control mainClock.

WRONG:

@Test
fun feedLoads() {
    composeRule.setContent { FeedScreen() }
    Thread.sleep(2_000)                                  // real time, flaky
    composeRule.onNodeWithText("Done").assertIsDisplayed()
}

RIGHT:

@Test
fun feedLoads() {
    composeRule.setContent { FeedScreen() }
    composeRule.waitUntilExactlyOneExists(hasText("Done"), timeoutMillis = 5_000)
    composeRule.onNodeWithText("Done").assertIsDisplayed()
}

MUST drive mainClock instead of sleeping through animations:

WRONG:

Thread.sleep(1_000) // let the animation finish

RIGHT:

composeRule.mainClock.autoAdvance = false
composeRule.mainClock.advanceTimeBy(1_000)

MUST NOT gate tests on external blocking (CountDownLatch) where a waitUntil API fits — external blocking does not advance the test clock.

2. Test rule choice

MUST use createComposeRule() for pure composable content and createAndroidComposeRule<Activity>() when the test needs the Activity. MUST NOT pair ActivityScenarioRule (or a manually launched activity) with a ComposeTestRule — the activity is then launched twice, a classic source of flakiness.

WRONG:

@get:Rule val composeRule = createComposeRule()
@get:Rule val activityRule = ActivityScenarioRule(MainActivity::class.java)

RIGHT:

@get:Rule val composeRule = createAndroidComposeRule<MainActivity>()

3. Test dependencies

MUST declare, in the module holding the UI tests:

androidTestImplementation("androidx.compose.ui:ui-test-junit4:...")
debugImplementation("androidx.compose.ui:ui-test-manifest:...")

ui-test-junit4 provides the rules; ui-test-manifest registers the empty activity createComposeRule() needs (not required for createAndroidComposeRule<YourActivity>()).

4. Semantics-based assertions

MUST find nodes through semantics: onNodeWithText / onNodeWithTag / onNodeWithContentDescription, and assert visibility with assertIsDisplayed() — existence is not visibility. Add testTag or semantics { contentDescription = ... } only when no natural matcher exists; keep tags in a shared constants object.

WRONG:

composeRule.onNodeWithText("Submit").assertExists()   // exists ≠ visible
composeRule.onNodeWithTag("btn_1")                    // ad-hoc tag literal

RIGHT:

composeRule.onNodeWithText("Submit").assertIsDisplayed()
composeRule.onNodeWithTag(TestTags.Submit)            // shared constants

This section is review-verified (no deterministic check): the checks cannot see which matcher fits your UI.

Verification

Run after every Compose test edit (from the project root):

bash <skill-dir>/checks/check_no_sleep_in_compose_tests.sh <src-dir>
bash <skill-dir>/checks/check_no_activity_scenario_rule.sh <src-dir>
bash <skill-dir>/checks/check_ui_test_dependencies.sh      <project-or-src-dir>

All three must pass (exit 0) before declaring the task done. Checks are deterministic import/call-site heuristics — they catch the documented anti-patterns above, not every testing bug. Assertion quality (§4) is verified by review against references/testing.md.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.