RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
日本語の概要は準備中です。原文の説明を表示しています。
Red-green-refactor-lint workflow for RIPDPI plus test-double, FaultQueue, and golden-bless conventions. Use when building a feature or fixing a bug test-first. Not for Kotlin test syntax (use kotlin-test-patterns).
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Full test stack documentation: docs/testing.md. Do not duplicate it here -- read it when you need runner details, CI lanes, or fixture locations.
Repeat this cycle for every behavior change. Write the failing test before any implementation -- do not skip RED.
./gradlew staticAnalysis before considering the cycle complete.Never batch multiple behaviors into one cycle. One test, one behavior, one cycle.
# Single test method
./gradlew :core:engine:testDebugUnitTest --tests "ClassName.method name"
# Single test class
./gradlew :core:engine:testDebugUnitTest --tests "ClassName"
# Single module
./gradlew :core:engine:testDebugUnitTest
Replace :core:engine with the target module (:core:service, :core:data, :core:diagnostics).
# Single test
cargo nextest run --locked -p crate_name test_name
# Single crate
cargo nextest run --locked -p crate_name
# Full workspace
cargo nextest run --locked --workspace
Golden tests are read-only by default. If your change intentionally alters a contract:
# Bless all golden fixtures
bash scripts/tests/bless-telemetry-goldens.sh
# Manual single-suite bless
RIPDPI_BLESS_GOLDENS=1 ./gradlew :core:engine:testDebugUnitTest
RIPDPI_BLESS_GOLDENS=1 cargo test --locked -p crate_name
Always review blessed diffs before committing. Golden changes require explanation in the commit message.
All test doubles are hand-written Fakes in core/engine/src/test/kotlin/com/poyka/ripdpi/core/TestDoubles.kt. The project does not use MockK, Mockito, or any mocking library.
Pattern:
Fake + interface name (e.g., FakeRipDpiProxyRuntime)Fault injection uses FaultQueue<T> from core/engine-api/src/main/kotlin/com/poyka/ripdpi/core/testing/FaultModel.kt.
Key types:
FaultQueue<T> -- ordered queue of faults matched by target enumFaultSpec<T> -- target + outcome + scope + optional message/payloadFaultScope.ONE_SHOT -- fires once then is consumedFaultScope.PERSISTENT -- fires on every matching call until clearedFaultOutcome -- EXCEPTION, TIMEOUT, DROP, RESET, MALFORMED_PAYLOAD, BLANK_PAYLOAD, PANICUsage in tests:
val bindings = FakeRipDpiProxyBindings()
bindings.faults.enqueue(
FaultSpec(
target = ProxyBindingFaultTarget.START,
outcome = FaultOutcome.EXCEPTION,
message = "simulated native crash",
)
)
| What you test | Location | Runner |
|---|---|---|
| Kotlin business logic | core/*/src/test/ | ./gradlew :core:*:testDebugUnitTest |
| Rust native logic | native/rust/crates/*/tests/ | cargo nextest run --locked -p crate |
| JNI integration | app/src/androidTest/.../integration/ | connectedGithubFullDebugAndroidTest |
| Network E2E | app/src/androidTest/.../e2e/ | connectedGithubFullDebugAndroidTest |
| Rust network E2E | native/rust/crates/*/tests/ | bash scripts/ci/run-rust-network-e2e.sh |
For non-trivial features, use context isolation:
This prevents the "write test and implementation together" anti-pattern.
TestDoubles.kt.FaultSpec + FaultQueue, not ad-hoc exception throwing.@Test fun proxy start propagates native exception().fn proxy_start_propagates_native_exception().| Mistake | Fix |
|---|---|
| Using MockK or Mockito | Write a Fake* class in TestDoubles.kt |
| Skipping the RED step | Run the test first. If it passes, your test is wrong. |
| Multiple assertions per cycle | Split into separate test methods, one behavior each |
runBlocking in coroutine tests | Use runTest from kotlinx-coroutines-test |
| Blessing goldens without review | Run git diff on fixture files before committing |
| Testing private internals | Test through the public API of the class under test |
| Putting helpers in test classes | Add shared helpers to TestDoubles.kt |
FaultScope.PERSISTENT when ONE_SHOT suffices | Default to ONE_SHOT; use PERSISTENT only for repeated-call scenarios |
For deeper coverage of anti-patterns, see references/testing-anti-patterns.md.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
日本語の概要は準備中です。原文の説明を表示しています。
ADB-based RIPDPI device/emulator debugging: build/install/launch, logcat filtering, fixture port-forwarding, instrumented tests, crash/ANR triage. Use when debugging on a real device or emulator.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium launch-contract reference: start routes and permission/service/data presets. Use when a test launches to the wrong screen or a new automation route is added. General flakiness: appium-test-debug.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium test authoring: page objects, resource-id locators, assertions, wait tiers. Use when writing a new Appium test or page object, or adding coverage for a new screen.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium failure triage: flaky tests, locator/session/wait issues, screenshot and element-tree debugging. Use when an Appium test fails or is flaky.
日本語の概要は準備中です。原文の説明を表示しています。
Add or modify a GitHub Actions job. Use when editing a file under .github/workflows/. Not for running a workflow locally (local-ci-act) or release signing (release-signing).
日本語の概要は準備中です。原文の説明を表示しています。