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).
日本語の概要は準備中です。原文の説明を表示しています。
Golden-fixture contract discipline: locations, bless workflow, env vars, volatile-field scrubbing, failure-artifact triage. Use when a golden/snapshot test fails or a new golden fixture is added.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Golden contracts enforce compatibility for telemetry, diagnostics events, strategy-probe progress/report payloads, and exported data. Fixtures are read-only by default -- tests fail on unexpected diffs. Bless with RIPDPI_BLESS_GOLDENS=1 to update.
Full documentation: docs/testing.md (Golden contracts section).
| Layer | Location | Examples |
|---|---|---|
| Rust | native/rust/crates/{crate}/tests/golden/ | android-support, ripdpi-android, ripdpi-tunnel-android, ripdpi-monitor-engine |
| JVM | core/{module}/src/test/resources/golden/ | engine, service, diagnostics |
| Android instrumentation | app/src/androidTest/assets/golden/ | Copies of JVM fixtures for on-device smoke tests |
| Variable | Purpose | Default |
|---|---|---|
RIPDPI_BLESS_GOLDENS | Set to any value to write fixtures instead of comparing | Not set (read-only) |
RIPDPI_GOLDEN_ARTIFACT_DIR | Override diff artifact output directory | target/golden-diffs (Rust), build/golden-diffs/ (JVM) |
bash scripts/tests/bless-telemetry-goldens.sh
This script:
android-support, ripdpi-android, ripdpi-tunnel-android, ripdpi-monitor-engine)NativeTelemetryGoldenTest, ServiceTelemetryGoldenTest)app/src/androidTest/assets/golden/)# Rust
RIPDPI_BLESS_GOLDENS=1 cargo test --locked -p ripdpi-android --manifest-path native/rust/Cargo.toml
# Kotlin
RIPDPI_BLESS_GOLDENS=1 ./gradlew :core:engine:testDebugUnitTest --tests "*.NativeTelemetryGoldenTest"
git diff -- verify changes are intentionalOn mismatch, both Rust and JVM support libraries write three files:
| File | Content |
|---|---|
{name}.expected | The golden fixture content |
{name}.actual | What the test produced |
{name}.diff | Unified diff between expected and actual |
Rust: Written to target/golden-diffs/ (or RIPDPI_GOLDEN_ARTIFACT_DIR).
JVM: Written to {module}/build/golden-diffs/.
golden-test-support Crateuse golden_test_support::{assert_text_golden, canonicalize_json, canonicalize_json_with};
// Simple text comparison
assert_text_golden(env!("CARGO_MANIFEST_DIR"), "tests/golden/output.json", &actual);
// JSON with key sorting
let canonical = canonicalize_json(&json_string)?;
assert_text_golden(env!("CARGO_MANIFEST_DIR"), "tests/golden/data.json", &canonical);
// JSON with custom scrubbing
let canonical = canonicalize_json_with(&json_string, |value| {
// Remove volatile fields like timestamps
scrub_timestamps(value);
})?;
assert_text_golden(env!("CARGO_MANIFEST_DIR"), "tests/golden/data.json", &canonical);
GoldenContractSupport ObjectLocated in core/engine/src/test/kotlin/com/poyka/ripdpi/core/GoldenContractSupport.kt:
// JSON comparison with canonical key ordering
GoldenContractSupport.assertJsonGolden(
"snapshot.json",
json.encodeToString(serializer, data),
)
// JSON with custom scrubbing
GoldenContractSupport.assertJsonGolden(
"snapshot.json",
json.encodeToString(serializer, data),
::scrubVolatileFields, // (JsonElement) -> JsonElement
)
// Plain text comparison
GoldenContractSupport.assertTextGolden("output.txt", actualText)
Fields that change between runs must be scrubbed for deterministic comparison:
Scrubbed (non-deterministic):
serviceStartedAt, lastFailureAt, updatedAt, capturedAt, createdAt)Strict (must match exactly):
private fun scrubVolatileFields(value: JsonElement): JsonElement =
when (value) {
is JsonObject -> JsonObject(
value.mapValues { (key, element) ->
when (key) {
"serviceStartedAt", "lastFailureAt", "updatedAt",
"capturedAt", "createdAt" -> Json.parseToJsonElement("0")
else -> scrubVolatileFields(element)
}
},
)
else -> value
}
Add golden-test-support to [dev-dependencies] in the crate's Cargo.toml:
[dev-dependencies]
golden-test-support = { path = "../golden-test-support" }
Write the test:
#[test]
fn my_output_matches_golden() {
let actual = produce_output();
let canonical = canonicalize_json(&serde_json::to_string(&actual).unwrap()).unwrap();
assert_text_golden(env!("CARGO_MANIFEST_DIR"), "tests/golden/my_output.json", &canonical);
}
Create initial fixture: RIPDPI_BLESS_GOLDENS=1 cargo test --locked -p my-crate my_output_matches_golden
Review and commit the new fixture file.
Write the test using GoldenContractSupport:
@Test
fun myOutputMatchesGolden() {
val actual = produceOutput()
GoldenContractSupport.assertJsonGolden("my_output.json", jsonEncode(actual))
}
Create initial fixture: RIPDPI_BLESS_GOLDENS=1 ./gradlew :module:testDebugUnitTest --tests "*.MyGoldenTest"
Review and commit the new fixture file.
If the new golden is needed for Android instrumentation tests:
cp line to scripts/tests/bless-telemetry-goldens.shapp/src/androidTest/assets/golden/| Mistake | Fix |
|---|---|
| Blessing without reviewing diffs | Always git diff after blessing. Unexpected changes may indicate bugs. |
| Forgetting to scrub volatile fields | New timestamp/ID fields cause non-deterministic failures. Add to scrub function. |
| Not explaining golden changes in commit | Golden updates should always explain why the expected output changed. |
| Missing instrumentation sync | JVM fixture updated but app/src/androidTest/assets/golden/ not. Run bless script or add cp manually. |
Adding golden without canonicalize_json | JSON key order is non-deterministic. Always canonicalize before comparing. |
| Hardcoding fixture path | Rust: use env!("CARGO_MANIFEST_DIR"). Kotlin: GoldenContractSupport resolves repo root automatically. |
docs/testing.md -- Full test stack documentation including golden contracts sectionnative/rust/crates/golden-test-support/src/lib.rs -- Rust support library sourcecore/engine/src/test/kotlin/.../GoldenContractSupport.kt -- Kotlin support library sourcescripts/tests/bless-telemetry-goldens.sh -- Blessing scriptまだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
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).
日本語の概要は準備中です。原文の説明を表示しています。