QA
dutradotdev/quokka
Run quokka's real-device E2E layer (QA strategy layer 5): drive the real qk binary against connected iPhone/Android devices through tmux, apply deterministic verifiers, and write a report.
A skill your agent uses to apply Android-team testing strategies — determinism, hermetic execution, Given-When-Then / Arrange-Act-Assert structure, naming conventions, and Hilt-based dependency…
$ npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install skydoves/android-testing-skills applying-testing-strategies --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/fundamentals/strategies/applying-testing-strategies .claude/skills/applying-testing-strategies && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "applying-testing-strategies" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategies into .claude/skills/applying-testing-strategies/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "applying-testing-strategies", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategiesType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install skydoves/android-testing-skills applying-testing-strategies --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/fundamentals/strategies/applying-testing-strategies .agents/skills/applying-testing-strategies && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "applying-testing-strategies" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategies into .agents/skills/applying-testing-strategies/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "applying-testing-strategies", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install skydoves/android-testing-skills applying-testing-strategies --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/fundamentals/strategies/applying-testing-strategies .cursor/skills/applying-testing-strategies && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "applying-testing-strategies" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategies into .cursor/skills/applying-testing-strategies/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "applying-testing-strategies", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/skydoves/android-testing-skills.git --path fundamentals/strategies/applying-testing-strategies--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install skydoves/android-testing-skills applying-testing-strategies --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/fundamentals/strategies/applying-testing-strategies .gemini/skills/applying-testing-strategies && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "applying-testing-strategies" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategies into .gemini/skills/applying-testing-strategies/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "applying-testing-strategies", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install skydoves/android-testing-skills applying-testing-strategiesInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/fundamentals/strategies/applying-testing-strategies .github/skills/applying-testing-strategies && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "applying-testing-strategies" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategies into .github/skills/applying-testing-strategies/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "applying-testing-strategies", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install skydoves/android-testing-skills applying-testing-strategies --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/fundamentals/strategies/applying-testing-strategies .opencode/skills/applying-testing-strategies && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "applying-testing-strategies" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/fundamentals/strategies/applying-testing-strategies into .opencode/skills/applying-testing-strategies/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "applying-testing-strategies", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
applying-testing-strategiesA skill your agent uses to apply Android-team testing strategies — determinism, hermetic execution, Given-When-Then / Arrange-Act-Assert structure, naming conventions, and Hilt-based dependency…
Applying Testing Strategies is an agent skill from skydoves/android-testing-skills. Use this skill to apply Android-team testing strategies — determinism, hermetic execution, Given-When-Then / Arrange-Act-Assert structure, naming conventions, and Hilt-based dependency replacement. Encodes which guidance actually lives on /training/testing/fundamentals/strategies (qualitative pyramid, network-access table) versus /training/testing/instrumented-tests/stability (determinism / flake) versus /training/dependency-injection/hilt-testing (@HiltAndroidTest, HiltAndroidRule, @TestInstallIn…
Its SKILL.md is about 5.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Test strategy and Design patterns. It works with Android. The repository describes itself as: ⚡️ A set of skills for Android testing: Compose UI, AndroidX Test, JVM unit tests, and ADB. The licence is Apache-2.0.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 8665ed5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are kotlin).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Applying Testing Strategies loads about 5.4k tokens when it runs. Until then it costs about 218 tokens; SKILL.md has 1,594 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from skydoves/android-testing-skills at commit 8665ed5, republished under its Apache-2.0 licence (© skydoves). 1,594 words, ~5,416 tokens.
.claude/skills/applying-testing-strategies/SKILL.md (or your agent's skills folder).A test suite needs three things to scale: it must be deterministic (same input → same outcome), structured (any reader can locate Given/When/Then), and replaceable (a single binding swap reroutes the production graph to fakes). This skill encodes Google's strategy guidance — flagging which page each rule actually lives on — and the Hilt mechanics that wire it into the build.
@HiltAndroidTest, HiltAndroidRule, @TestInstallIn, @UninstallModules, @BindValue, or rule ordering.RuleChain.outerRule for combining HiltAndroidRule with ActivityScenarioRule or composeTestRule.../../concepts/understanding-the-testing-pyramid/SKILL.md.../../concepts/choosing-what-to-test/SKILL.md.../../doubles/picking-test-doubles/SKILL.md.../organizing-test-source-sets/SKILL.md.../../../compose/synchronization/synchronizing-with-idle/SKILL.md.../../concepts/understanding-the-testing-pyramid/SKILL.md.dagger.hilt.android.testing.HiltAndroidRule and dagger.hilt.android.testing.HiltAndroidTest available on androidTestImplementation.kotlinx-coroutines-test, Robolectric (if host tests), and the ability to stub System.currentTimeMillis() / Clock.systemDefaultZone().Per tasks/research/R8-android-fundamentals.md, the strategy concepts live on three different pages. Naming the source matters because PR reviewers cite skills.
| Concept | Page that actually documents it |
|---|---|
| Qualitative pyramid ("many small, few big") | /training/testing/fundamentals/strategies |
| Five-level Unit/Component/Feature/Application/RC table | /training/testing/fundamentals/strategies |
| Network access per layer | /training/testing/fundamentals/strategies |
| Determinism / flake handling | /training/testing/instrumented-tests/stability (NOT /strategies) |
| Hermetic test definition | /training/testing/fundamentals/test-doubles (in passing) |
| Given-When-Then comment style | NEVER named on any page; only used in code samples |
| Arrange-Act-Assert | NEVER named on any page |
| Test naming | Only the backtick caveat on /training/testing/instrumented-tests |
@HiltAndroidTest, HiltAndroidRule, @TestInstallIn, @UninstallModules, @BindValue | /training/dependency-injection/hilt-testing |
MUST NOT attribute determinism guidance to /strategies — it is on /instrumented-tests/stability. MUST NOT claim Google "recommends Given-When-Then" — the pages do not say that; they only use the comment style in samples.
Per /training/testing/instrumented-tests/stability (and CORPUS §C "Common gotchas"), four sources of non-determinism dominate:
System.currentTimeMillis(), Clock.systemDefaultZone(), Instant.now(). Inject a Clock or use kotlinx-coroutines-test's virtual time.Dispatchers.IO, runBlocking, real delay. Use runTest, inject CoroutineDispatcher, replace Dispatchers.Main via Dispatchers.setMain(dispatcher). See ../../../jvm-tests/coroutines/testing-coroutines-with-runtest/SKILL.md.MainTestClock, View animations. Disable via testOptions.animationsDisabled = true (Gradle) or Settings.Global.WINDOW_ANIMATION_SCALE = 0 (ADB). For Compose: mainClock.autoAdvance = false per the skydoves directives in docs/SPEC.md §5.Random(), UUID.randomUUID(). Inject seeds, use fakes, run pm clear before each instrumented test.Concrete checklist:
Clock (or equivalent time source) is injected; tests substitute Clock.fixed(Instant.parse(...), ZoneId.of("UTC")).Dispatchers are injected via a DispatcherProvider interface or replaced with Dispatchers.setMain(StandardTestDispatcher()) in a @Before.Random is seeded (Random(42)) or wrapped behind a RandomProvider that the test substitutes.testOptions.animationsDisabled = true is set in build.gradle.kts.pm clear <pkg> before every instrumented test (Test Orchestrator does this automatically; otherwise add an @Before).The /strategies page does NOT formalize "hermetic" as a top-level term. The closest definition is on /test-doubles:
"A hermetic test avoids all external dependencies, such as fetching data from the internet." —
developer.android.com/training/testing/fundamentals/test-doubles
The operational rule is on /strategies:
| Layer | Network access |
|---|---|
| Unit | None |
| Component | None |
| Feature | "supports mocked network access" |
| Application | n/a |
| Release Candidate | n/a |
MUST NOT present "hermetic" as if it were a dedicated section on /strategies — it is mentioned in passing on /test-doubles only. MUST cite both pages when discussing hermeticity: /test-doubles for the term, /strategies for the operational rule.
Neither pattern is named on any of the four primary pages (/fundamentals, /what-to-test, /test-doubles, /strategies). They are visibly used in Google's code samples. From /fundamentals:
// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)
// When data is loaded
viewModel.loadData()
// Then it should be exposing data
assertTrue(viewModel.data != null)— developer.android.com/training/testing/fundamentals (Local/host-side unit test example)
And from the same page:
// When the Continue button is clicked
onView(withText("Continue")).perform(click())
// Then the Welcome screen is displayed
onView(withText("Welcome")).check(matches(isDisplayed()))— developer.android.com/training/testing/fundamentals (Espresso example)
Cite "Google's official samples consistently use Given-When-Then comment blocks" — accurate. Do NOT cite "Google recommends Given-When-Then" — that is fabrication.
Both Given-When-Then and Arrange-Act-Assert are the same shape with different vocabulary:
Given (Arrange) — set up the SUT and dependencies
When (Act) — invoke the behavior under test
Then (Assert) — assert on the resulting state or interactionPick one vocabulary per repo (skydoves preference: Given-When-Then, matching Google's samples). Use it as inline comment blocks, not as method names.
The only verbatim naming guidance across the four primary pages is the backtick caveat on /instrumented-tests:
"Note: Using backticks to name tests in Kotlin is only supported on devices running API 30 and above." —
developer.android.com/training/testing/instrumented-tests
Implications:
src/test/) — backtick names are safe (run on JVM, not the Android runtime).src/androidTest/) — backtick names require minSdk >= 30 on the test APK. Below that, use camelCase or snake_case_with_underscores.skydoves convention (combine these two facts): a methodName_state_expected shape that reads as a sentence.
loadUsers_emptyList_emitsEmptyState
applyCoupon_negativeTotal_emitsError
save_orchestratorMarksDirtyOnceSource: developer.android.com/training/dependency-injection/hilt-testing plus CORPUS §F.6.
"Hilt isn't necessary for unit tests, since when testing a class that uses constructor injection, you don't need to use Hilt to instantiate that class." —
developer.android.com/training/dependency-injection/hilt-testing
"For integration tests, Hilt injects dependencies as it would in your production code. Testing with Hilt requires no maintenance because Hilt automatically generates a new set of components for each test." —
developer.android.com/training/dependency-injection/hilt-testing
So: constructor-inject in unit tests (skip Hilt), use Hilt in UI / integration tests.
@HiltAndroidTest + HiltAndroidRule ordered first@HiltAndroidTest
class HomeScreenTest {
@get:Rule(order = 0) val hiltRule = HiltAndroidRule(this)
@get:Rule(order = 1) val composeRule = createAndroidComposeRule<MainActivity>()
@Inject lateinit var userRepository: UserRepository
@Before fun inject() = hiltRule.inject()
}HiltAndroidRule MUST execute before any rule that touches the injected graph (Activity launch, Compose setup). The /hilt-testing page phrases this as "the HiltAndroidRule executes first". Lower order values run first in JUnit4 (@Rule(order = 0) outranks order = 1), so the conventional pattern is 0 then 1 as shown — but the rule is "Hilt first", not specifically "order = 0". Negative numbers also work (order = -1 paired with order = 0), and any monotonically increasing scheme is fine. Per /hilt-testing:
"You must annotate any UI test that uses Hilt with
@HiltAndroidTest. This annotation is responsible for generating the Hilt components for each test. Also, you need to add theHiltAndroidRuleto the test class." —developer.android.com/training/dependency-injection/hilt-testing
"To inject types into a test, use
@Injectfor field injection. To tell Hilt to populate the@Injectfields, callhiltRule.inject()." —developer.android.com/training/dependency-injection/hilt-testing
@TestInstallIn — replace a binding for ALL tests@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [AnalyticsModule::class],
)
abstract class FakeAnalyticsModule {
@Singleton @Binds
abstract fun bindAnalyticsService(impl: FakeAnalyticsService): AnalyticsService
}The replacement applies to every @HiltAndroidTest in the module. Use this when the same fake fits every test (in-memory DB, no-op analytics).
@UninstallModules — replace in a SINGLE test@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest {
@Module @InstallIn(SingletonComponent::class)
abstract class TestModule {
@Singleton @Binds
abstract fun bindAnalyticsService(impl: FakeAnalyticsService): AnalyticsService
}
}Per /hilt-testing warnings (must surface in skills):
"Warning: You cannot uninstall modules that are not annotated with
@InstallIn. Attempting to do so causes a compilation error."
"Warning:
@UninstallModulescan only uninstall@InstallInmodules, not@TestInstallInmodules." —developer.android.com/training/dependency-injection/hilt-testing
@BindValue — quick swap for a single test@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest {
@BindValue @JvmField
val analyticsService: AnalyticsService = FakeAnalyticsService()
}@BindValue is the lightweight form — no test module class. Use when the test wants to seed a single instance and assert on it.
@CustomTestApplication — non-Hilt base classWhen the production Application extends a non-Hilt base (MultiDexApplication, a vendor app class), Hilt cannot generate the test app automatically. Use:
@CustomTestApplication(BaseApplication::class)
interface HiltTestApplicationThe generated HiltTestApplication_Application is then named in testInstrumentationRunnerArguments or via a custom AndroidJUnitRunner.
@HiltAndroidTest
class SettingsActivityTest {
@get:Rule(order = 0) var hiltRule = HiltAndroidRule(this)
@get:Rule(order = 1) var settingsActivityTestRule = SettingsActivityTestRule(...)
}— developer.android.com/training/dependency-injection/hilt-testing
Or with RuleChain for mid-chain composition:
@get:Rule
val chain: TestRule = RuleChain
.outerRule(HiltAndroidRule(this))
.around(InstantTaskExecutorRule())
.around(MainDispatcherRule())// WRONG — no structure; reader cannot find the act vs assert boundary
@Test
fun loadsUser() = runTest {
val repo = FakeUserRepository().apply { seed(User(UserId("u1"), "Alice")) }
val vm = UserViewModel(repo)
vm.load(UserId("u1"))
val state = vm.state.value
assertEquals("Alice", state.name)
assertFalse(state.isLoading)
}
// WRONG because: the test crams setup, action, and assertion together. With three or
// more lines per stage, readers cannot locate failures fast. Google's own samples use
// Given-When-Then comments as visual separators.// RIGHT
@Test
fun loadUser_seededId_emitsLoadedState() = runTest {
// Given a fake repo seeded with Alice
val repo = FakeUserRepository().apply { seed(User(UserId("u1"), "Alice")) }
val vm = UserViewModel(repo)
// When loading the seeded id
vm.load(UserId("u1"))
// Then the state is Loaded with Alice
assertEquals(UserUiState.Loaded(name = "Alice"), vm.state.value)
}// WRONG
@HiltAndroidTest
class HomeScreenTest {
@get:Rule val composeRule = createAndroidComposeRule<MainActivity>() // order = 0 by default
@get:Rule val hiltRule = HiltAndroidRule(this)
}
// WRONG because: with no order, JUnit picks ordering implementation-defined. The
// Activity may launch before Hilt's component is built, throwing at @Inject sites.
// Per /hilt-testing, HiltAndroidRule must run first.// RIGHT
@HiltAndroidTest
class HomeScreenTest {
@get:Rule(order = 0) val hiltRule = HiltAndroidRule(this)
@get:Rule(order = 1) val composeRule = createAndroidComposeRule<MainActivity>()
}// WRONG
class DueDateTest {
@Test fun reportsOverdue() {
val task = Task(dueAt = Instant.now().minusSeconds(60))
assertTrue(task.isOverdue()) // depends on real wall clock; flake risk on slow CI
}
}// RIGHT
class DueDateTest {
private val fixedNow = Instant.parse("2024-01-01T00:00:00Z")
private val clock = Clock.fixed(fixedNow, ZoneId.of("UTC"))
@Test fun reportsOverdue() {
val task = Task(dueAt = fixedNow.minusSeconds(60), clock = clock)
assertTrue(task.isOverdue())
}
}@BindValue over every { }// WRONG — mocking a Hilt-injected real instance
@HiltAndroidTest
class SettingsActivityTest {
@get:Rule(order = 0) val hiltRule = HiltAndroidRule(this)
@Inject lateinit var analytics: AnalyticsService
@Test fun tracks() {
// analytics is the real production instance; tests now mutate prod state
every { (analytics as RealAnalyticsService).enabled = false } // does not compile
}
}// RIGHT — replace at the binding boundary
@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest {
@BindValue @JvmField
val analytics: AnalyticsService = FakeAnalyticsService()
@get:Rule(order = 0) val hiltRule = HiltAndroidRule(this)
}HiltAndroidRule to execute first when combined with any rule that touches the injected graph (Activity, Compose, Fragment, Coroutine). The conventional shape is @Rule(order = 0) on Hilt and @Rule(order = 1) on the next rule, but any monotonic ordering that puts Hilt first is fine — /hilt-testing says "the HiltAndroidRule executes first", not specifically order = 0.hiltRule.inject() in @Before for any test class with @Inject fields.@TestInstallIn-replaced module with @UninstallModules — Hilt fails compilation per the page's warning box./training/testing/fundamentals/strategies. Use /training/testing/instrumented-tests/stability.Clock (or equivalent time source), DispatcherProvider, and Random seed for any code whose output depends on them.camelCase_state_expected (per /instrumented-tests: "Using backticks to name tests in Kotlin is only supported on devices running API 30 and above" — the gate is the runtime device API, not just the module's minSdk).@BindValue for single-test binding swaps, @TestInstallIn for module-wide swaps.testOptions.animationsDisabled = true rather than per-test ADB shell calls.@HiltAndroidTest class declares HiltAndroidRule with an order that places it first relative to any other JUnit rules in the class (@Rule(order = 0) is the conventional choice).@HiltAndroidTest class with @Inject fields calls hiltRule.inject() in @Before.Fake* classes; all fakes live under src/androidTest/ or src/test/ (or a dedicated core-testing module).Instant.now(), System.currentTimeMillis(), or Random() without a seed/injection.testOptions.animationsDisabled = true set in module build.gradle.kts.developer.android.com/training/testing/fundamentals/strategies — qualitative pyramid, network-access table per layer.developer.android.com/training/testing/fundamentals/test-doubles — hermetic-test definition (in passing).developer.android.com/training/testing/instrumented-tests/stability — determinism / flake guidance (NOT on /strategies).developer.android.com/training/testing/instrumented-tests — backtick naming caveat ("Using backticks ... only supported on devices running API 30 and above").developer.android.com/training/dependency-injection/hilt-testing — @HiltAndroidTest, HiltAndroidRule, @TestInstallIn, @UninstallModules, @BindValue, @CustomTestApplication, the warning boxes, the rule-ordering example.tasks/research/R8-android-fundamentals.md — verbatim Hilt quotes and the source-of-truth map per page.MainDispatcherRule JUnit4 wrapper at testutils/testutils-ktx/src/jvmMain/kotlin/androidx/testutils/MainDispatcherRule.jvm.kt.../../concepts/understanding-the-testing-pyramid/SKILL.md, ../../concepts/choosing-what-to-test/SKILL.md, ../../doubles/picking-test-doubles/SKILL.md, ../organizing-test-source-sets/SKILL.md.../../../jvm-tests/coroutines/testing-coroutines-with-runtest/SKILL.md, ../../../jvm-tests/coroutines/testing-flows-with-turbine/SKILL.md, ../../../jvm-tests/runner/configuring-junit4-on-android/SKILL.md, ../../../jvm-tests/robolectric/using-robolectric-correctly/SKILL.md, ../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md, ../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md, ../../../adb/observability/extracting-logs-with-logcat/SKILL.md.© skydoves, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in fundamentals/strategies/applying-testing-strategies of skydoves/android-testing-skills.
Open the folder on GitHubat commit 8665ed5
Applying Testing Strategies next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Applying Testing Strategies this skillskydoves/android-testing-skills | 333 | — | ~5.4k | Automated safety check: Pass | Apache-2.0 | |
| QAdutradotdev/quokka | 108 | — | ~1k | Automated safety check: Pass | MIT | |
| Nestjs Expertdavila7/claude-code-templates | 32k | 7 repos | ~5.3k | Automated safety check: Notes | MIT | |
| Android TestingMoustachauve/WLED-Android | 169 | 3 repos | ~731 | Automated safety check: Pass | Apache-2.0 | |
| Testing Setuparindamxd/camerax-android | 132 | 4 repos | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| Testing Principlesshinpr/claude-code-workflows | 693 | — | ~1.1k | Automated safety check: Pass | MIT |
dutradotdev/quokka
Run quokka's real-device E2E layer (QA strategy layer 5): drive the real qk binary against connected iPhone/Android devices through tmux, apply deterministic verifiers, and write a report.
davila7/claude-code-templates
Nest.js framework expert specializing in module architecture, dependency injection, middleware, guards, interceptors, testing with Jest/Supertest, TypeORM/Mongoose integration, and Passport.js…
Moustachauve/WLED-Android
Comprehensive testing strategy involving Unit, Integration, Hilt, and Screenshot tests.
arindamxd/camerax-android
Analyze and create a testing strategy for native Android apps - install testing libraries, set up test infrastructure, create harnesses for unit tests, UI tests, screenshot tests, and end-to-end…
shinpr/claude-code-workflows
Language-agnostic testing principles including TDD, test quality, coverage standards, and test design patterns.
DevAtrii/Kmp-Starter-Template
Build production Android & iOS apps on the KMP Starter Template (Clean Architecture, MVI, Koin, Compose Multiplatform).
skydoves/android-testing-skills
A skill your agent uses to verify Compose layout measurements from a UI test using assertWidthIsEqualTo, assertHeightIsEqualTo, assertWidthIsAtLeast, assertHeightIsAtLeast…
skydoves/android-testing-skills
A skill your agent uses to verify a Compose semantics node's properties from a UI test using assertExists, assertDoesNotExist, assertIsDisplayed, assertIsNotDisplayed, assertIsDeactivated…
skydoves/android-testing-skills
A skill your agent uses to render every Jetpack Compose @Preview as a screenshot on a real Android device or emulator and publish a browsable HTML catalog from CI.
skydoves/android-testing-skills
A skill your agent uses to capture visual artefacts from a device for test failures, golden image generation, QA repro, and demo videos.
skydoves/android-testing-skills
A skill your agent uses to pick the correct Compose UI test entry point.
skydoves/android-testing-skills
A skill your agent uses to pick which behaviors to cover in an Android test suite using Google's five-category state vocabulary plus the explicit "what NOT to test" list from…
Works with
Categories
A skill your agent uses to apply Android-team testing strategies — determinism, hermetic execution, Given-When-Then / Arrange-Act-Assert structure, naming conventions, and Hilt-based dependency…. Applying Testing Strategies is an agent skill from skydoves/android-testing-skills. Use this skill to apply Android-team testing strategies — determinism, hermetic execution, Given-When-Then / Arrange-Act-Assert structure, naming conventions, and Hilt-based dependency replacement.
Applying Testing Strategies fits situations like: apply Android-team testing strategies — determinism; hermetic execution; given-When-Then / Arrange-Act-Assert structure; naming conventions.
Run `npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a claude-code`. Or copy the skill folder (fundamentals/strategies/applying-testing-strategies in skydoves/android-testing-skills) into .claude/skills/applying-testing-strategies in your project. Claude Code loads it when a task matches its description.
Run `npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a codex`. Or copy the skill folder (fundamentals/strategies/applying-testing-strategies in skydoves/android-testing-skills) into .agents/skills/applying-testing-strategies in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add skydoves/android-testing-skills --skill applying-testing-strategies -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/applying-testing-strategies, .gemini/skills/applying-testing-strategies, .github/skills/applying-testing-strategies and .opencode/skills/applying-testing-strategies in your project.
SKILL.md names no scripts, command-line tools or credentials: Applying Testing Strategies is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Applying Testing Strategies is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.4k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Applying Testing Strategies: QA (dutradotdev/quokka, 108 stars), Nestjs Expert (davila7/claude-code-templates, 32k stars), Android Testing (Moustachauve/WLED-Android, 169 stars) and Testing Setup (arindamxd/camerax-android, 132 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
skydoves (a GitHub user) maintains it in skydoves/android-testing-skills, which has 333 GitHub stars. The repository holds 50 skills in this directory. The repository was last updated on May 25, 2026.
Source: skydoves/android-testing-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.