auditing-compose-test-suite について
既存の Jetpack Compose テストを6段階で順に監査し、問題を担当する関連 Skill に案内するインデックス型の Skill です。テスト設定や信頼性を確認する開発者向けで、コード自体は変更しません。
主な機能
- 016段階の順序付き監査
- 02設定、検索、アサーション、操作、時間、診断を確認
- 03問題を関連 Skill に振り分け
- 04コードを変更しない
活用シーン
- 01既存の Compose テストファイルのレビュー
- 02不安定または遅い CI テストの調査
- 03Compose リリース前のテスト確認
- 04StandardTestDispatcher への移行評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill auditing-compose-test-suiteインストール後、Claude Code で/auditing-compose-test-suiteを入力して読み込まれたか確認します。
詳細
Compose テストスイートの監査 — 6 段階のレビューと、その後の振り分け
これはインデックス形式のスキルです。compose-test-skills/ 内の残りのスキルを決められた順序で連携させ、既存のテストファイルまたはテストスイートを監査します。各フェーズでは指摘事項が見つかり、それぞれの指摘事項から修正を担当する兄弟スキルへ案内します。監査自体はコードを変更しません。変更は振り分け先のスキルが担当します。
このスキルを使う場合
- ユーザーが
*Test.kt(または複数のファイル)を貼り付け、「どこが問題か」「レビューして」「監査して」と依頼した場合。 - ユーザーから、慢性的な不安定さ、遅い CI、「ローカルではテストが通るのに CI では失敗する」といった報告があった場合。
- ユーザーが Compose の機能をリリースする準備をしており、テストスイートの審査を求めている場合。
- ユーザーが v1(
UnconfinedTestDispatcher)から v2(StandardTestDispatcher)へ移行しており、問題が起きそうなテストのチェックリストを求めている場合。 - ユーザーが別のチームからテストファイルを引き継ぎ、何が正しくて何がたまたま動いているだけなのか分からない場合。
このスキルを使わない場合
- ユーザーが特定のアサーションの失敗を修正したい場合 — 該当する兄弟スキルに直接進みます(マッチャーの見落としなら、多くの場合
../../debug/printing-the-semantics-tree/SKILL.md、アニメーションの不安定さなら../../synchronization/testing-animations-deterministically/SKILL.md)。 - ユーザーがゼロから新しいテストを始める場合 — まず
../../setup/configuring-test-dependencies/SKILL.md、次に../../setup/choosing-test-rule-vs-runtest/SKILL.md、その後../../setup/setting-up-host-vs-device-tests/SKILL.mdに進みます。 - ユーザーが本番のコンポーザブルのパフォーマンスレビューを求めている場合 — 対象はこのリポジトリではなく
compose-performance-skillsです。
前提条件
- レビュー対象となるすべてのテストファイルへの読み取りアクセス。テストメソッドが1つだけでは監査の範囲が狭すぎます。クラス全体を通してパターンが現れます。
- モジュールの
build.gradle.kts(フェーズ1の依存関係チェック用)と、テストでカスタム Activity を使う場合はsrc/androidTest/AndroidManifest.xml。 ../docs/SPEC.md§5 に記載された skydoves の見解への理解(本番コードのtestTag、デフォルトのuseUnmergedTree = false、アニメーションではmainClock.autoAdvance = false、waitUntilは実時間、状態変更にはrunOnIdle、v2 のエントリポイントを優先、Thread.sleepは要注意)。
監査パイプライン
6つのフェーズを順番に実行します。いずれかのフェーズで指摘事項が見つかったら、そこで止めて該当する兄弟スキルへ振り分けます。前のフェーズでの修正により、後のフェーズの指摘事項が無効になることがあります(例:フェーズ1で v1 から v2 に切り替えると、フェーズ5のアイドル時の動作が変わる場合があります)。
フェーズ1 — セットアップの正確性
ビルド、@Rule、ソースセットの各層で確認すること:
- Gradle:
androidx.compose.ui:ui-test-manifestはdebugImplementation(インストルメンテーション)/testImplementation(ホスト)に指定されていますか?ui-test-junit4はテストクラスと同じ構成に指定されていますか? - Lint:
TestManifestGradleConfiguration(重大度 WARNING)が抑制されていますか? - Rule の選択:
createComposeRule()、createAndroidComposeRule<A>()、createEmptyComposeRule()のうち、選択した Rule はホストに合っていますか?カスタム Activity はsrc/androidTest/AndroidManifest.xmlに宣言されていますか? - v1 と v2 のインポート:
androidx.compose.ui.test.junit4.createComposeRuleまたはandroidx.compose.ui.test.runComposeUiTest(非推奨 WARNING)はありますか? - サーフェスの混在:同じテストクラスで
@get:Rule val rule = createComposeRule()とrunComposeUiTest { }の本体を両方宣言していますか? - ソースセット:ファイルは
src/test/(ホスト)とsrc/androidTest/(デバイス)のどちらにありますか?その機能セットは適切ですか(ホストではcaptureToImage、enableAccessibilityChecks、リップルに依存するアサーションを使用しないなど)?
失敗時の振り分け先:
- 依存関係の不足や設定ミス、
ActivityNotFoundException、lint 警告 →../../setup/configuring-test-dependencies/SKILL.md。 - Rule コンストラクタの誤り、v1 のインポート、サーフェスの混在、
setContentの二重呼び出し →../../setup/choosing-test-rule-vs-runtest/SKILL.md。 - ソースセットの誤り、ホストでのスクリーンショットテスト、ホストでのアクセシビリティチェック →
../../setup/setting-up-host-vs-device-tests/SKILL.md。
フェーズ 2 — Finder の使い分け
各 onNode* / onAllNodes* 呼び出しで確認すること:
- Finder の選択:
onNodeWithTag、onNodeWithText、onNodeWithContentDescriptionの使用数を確認します。i18n 対応されていない文字列に対するonNodeWithTextの多用は、脆弱性の兆候です。Skydoves の大胆な提案その 1:Modifier.testTag("…")は定数として本番コードに置きます。テストではテキストではなくタグで検索します。 - 本番コードでのタグの存在:一致したタグは、本番のコンポーザブルで
Modifier.testTag(...)によって実際に適用されていますか?適用されていない場合、Finder は一致しません。 useUnmergedTree:デフォルトはfalseです。開発者が理由を示さずに切り替えていませんか?マージされたサブツリー内のタグ(例:Button内のTextに付けられたタグ)をテストが前提として、誤った(親)ノードに一致していませんか?- セレクターチェーン:
onChild/onParentはuseUnmergedTreeを引き継ぎます。走査の途中でフラグを切り替えるチェーンは疑わしいです。 onAllNodes(...).filter(...)とカスタムのSemanticsMatcherの比較:テストで、既成のマッチャー(hasText、hasClickAction、hasContentDescription)を再実装していませんか?
失敗パターンの参照先:
- 本番コードにタグがない、テキスト Finder が脆弱 →
../../finders/finding-nodes-by-tag-text-content/SKILL.md - マージ済み/未マージの選択が誤っている、またはツリーのナビゲーションが脆弱 →
../../finders/traversing-the-semantics-tree/SKILL.md - 既成のマッチャーがあるのに独自のマッチャーを作成している →
../../finders/composing-semantics-matchers/SKILL.md - CI で Finder の一致数がゼロになる →
../../debug/printing-the-semantics-tree/SKILL.md
フェーズ 3 — アサーションの強さ
各 assert* 呼び出しで確認すること:
- テスト作成者が
assertIsDisplayed()のつもりでassertExists()を使っていませんか?セマンティクスツリーに存在することは、画面上に表示されていることより弱い条件です。 assertCountEquals(n)とassertAny(matcher)の比較:実際には「少なくとも 1 つが一致する」という意図なのに、コレクションのサイズにテストが過度に依存していませんか?- 境界と状態:
assertWidthIsEqualTo/getUnclippedBoundsInRootはレイアウトに対する状態チェックです。これらをスクリーンショットのアサーションと併用すると、作業が重複します。 - テキストのアサーション:ユーザーに表示される文字列に対する
assertTextEquals("Save")は i18n によってずれます。assertTextEquals(context.getString(R.string.save))のほうが堅牢です。 assertIsOn/assertIsOff/assertIsSelected:これらはトグル/選択可能なセマンティクスの状態を確認します。より弱いassertExistsを使うために省略されていませんか?Dp.assertIsEqualToの許容誤差:デフォルトは ½ dp です。許容誤差を設けるほうが妥当なのに、テストでピクセル単位の完全一致をアサーションしていませんか?
失敗パターンの参照先:
assertExistsの多用、意図に対して脆弱な件数チェック、トグル/選択可能な状態、テキストのアサーション →../../assertions/asserting-node-state-and-text/SKILL.md- 境界のチェック →
../../assertions/asserting-bounds-and-dimensions/SKILL.md
フェーズ 4 — アクションの正確性
各 perform* 呼び出しで確認すること:
performGesture { }:すべての箇所で@Deprecatedです。performTouchInput { }に置き換えてください。これは必須です。SPEC ではperformGestureの推奨を禁じています。- 座標系:
performTouchInput { down(Offset(x, y)) }はノード相対座標を使用します。グローバル座標を計算してノード相対の DSL に渡すテストでは、画面外をタップしてしまい、何も起きないことがあります。 - タッチ DSL 拡張機能:テストで、プリミティブな
down/moveBy/up呼び出しを使ってclick()/longClick()/swipeUp()/pinch(...)を再実装していませんか? 利用できる場合は、高レベルの拡張機能を使ってください。 - テキスト入力:
performTextInput("foo")は追記し、performTextReplacement("foo")は置換し、performTextClearance()は空にします。選択を誤ると、「foo」ではなく「fooSave」になります。 - IME アクション:
performImeAction()はKeyboardOptions.imeActionで設定されたアクションを実行します。performImeAction()が適切なのに、テストでEspresso.pressBack()やキーイベントを使っていませんか? - マルチモーダル:
performTouchInputとperformMouseInputを組み合わせるテストでは、単一ポインターイベントのタイムラインにするため、performMultiModalInput { touch { … }; mouse { … } }の使用を検討してください。 - スクロール:
performScrollToNode、performScrollToIndex、performScrollToKeyは LazyList に対応しています。テストでは、代わりに力ずくでswipeUpを使っていませんか?
失敗モードの参照先:
- 非推奨の
performGesture、座標の混同、スワイプのプリミティブ →../../actions/injecting-touch-gestures/SKILL.md。 - テキスト入力/置換/IME アクション →
../../actions/entering-text/SKILL.md。 - マウス、キー、マルチモーダル →
../../actions/injecting-mouse-and-keyboard/SKILL.md。 - スクロールコンテナー(
performScrollToIndex/Key/Node)、performClick→../../actions/clicking-and-scrolling/SKILL.md。 - 高レベルの LazyList パターン(可視性、
state.layoutInfo、アニメーション付きアイテム配置) →../../patterns/testing-lazy-lists/SKILL.md。
フェーズ 5 — 時間とアイドル状態の正確性
最も不安定になりやすいフェーズです。各テストメソッドを最初から最後まで確認してください。
Thread.sleep(N):リップルの完了を待つため、スクリーンショットテストで RenderThread を待機する場合を除き、どこでも禁止です。Skydoves の強い意見 #7 です。それ以外では、mainClock.advanceTimeBy(durationMs)(テストクロック)またはrule.waitUntil(timeoutMillis) { … }(実時間)に置き換えてください。- アニメーションテスト:アニメーションを開始するテストでは、
setContentの前に必ずmainClock.autoAdvance = falseを設定してください。そうしないと、インストールされたInfiniteAnimationPolicyが、無限アニメーションの開始直後にCancellationExceptionでキャンセルします。Skydoves の強い意見 #3 です。 - テストクロックと実時間:
mainClock.advanceTimeUntil { … }はテストクロックを使い、rule.waitUntil(timeoutMillis) { … }は実時間を使います。同じテストで両方を混在させると不安定になります。advanceTimeUntilがクロックの進行を待っている間に、waitUntilがタイムアウトすることがあります。Skydoves の強い意見 #4 です。 - スレッド外での状態変更:テストスレッドから(
runOnIdle/runOnUiThreadの中ではなく)state.value = Xを実行すると、リコンポーザーとの競合が発生します。Skydoves の強い意見 #5 です。 - v2 のキューに入れられた処理:
androidx.compose.ui.test.v2.*への移行後、LaunchedEffectはStandardTestDispatcherのキューに入れられます。以前はUnconfinedTestDispatcherの即時ディスパッチに依存していたテストでは、キューを空にするために明示的なmainClock.advanceTimeBy(0)またはrunCurrent()が必要になる場合があります。 waitUntilのタイムアウト:デフォルトは 1000 ms です。テストでは、欠落したIdlingResourceを覆い隠すため、またはクロックの誤りを隠すために、より長いタイムアウトを使っていませんか?
失敗モードの参照先:
Thread.sleep、IdlingResourceの欠落、waitUntilの混同、スレッド外での状態変更、外部処理用のカスタムIdlingResource→../../synchronization/synchronizing-with-idle/SKILL.md。- フレームの丸め、
advanceTimeByの粒度、v1/v2 ディスパッチャーの移行 →../../synchronization/controlling-the-test-clock/SKILL.md。 - アニメーションの不安定さ、
autoAdvanceの設定漏れ、InfiniteAnimationPolicyのCancellationException→../../synchronization/testing-animations-deterministically/SKILL.md。
フェーズ 6 — デバッグ出力
テストが失敗したときの出力を確認します。
printToLog/printToString:ファインダーが対象を見つけられなかった場合、失敗の原因を特定できるようにテストはセマンティクスツリーを出力しますか。それともAssertionError: failed: assertExistsを投げるだけですか?fetchSemanticsNode:直接呼び出している箇所はありますか?これはエスケープハッチです。控えめに使う分には問題ありませんが、多用されている場合は、テストが公開マッチャー API を迂回していることを示しています。- 失敗メッセージ:コレクションに対するマッチャーアサーションは、デフォルトのエラー(マッチしたノードとマッチしなかったノードをすべて列挙するもの)を使っていますか。それともカスタムの
try/catchで握りつぶされていますか? - テスト名:失敗したテスト名から、開発者は期待される動作を把握できますか。それとも
testButton1のような名前ですか?
以下の失敗パターンは、次のスキルに誘導します。
- 原因を特定できない失敗、対象が見つからないときのツリーダンプの欠落、
fetchSemanticsNodeの過剰使用 →../../debug/printing-the-semantics-tree/SKILL.md。 - アクセシビリティチェックのカバレッジ不足、Robolectric の何もしない動作に関する予想外の結果 →
../../debug/enabling-accessibility-checks/SKILL.md。
監査レポートのテンプレート
ユーザーが PR の説明に貼り付けられるよう、監査結果を Markdown テーブルで作成します。指摘事項ごとに 1 行を使います。フェーズは順番に実行しますが、同じフェーズ内の指摘事項は重大度順に並べ替えてかまいません。
| # | Phase | File:line | Severity | Finding | Routed skill |
|---|---|---|---|---|---|
| 1 | 1 setup | build.gradle.kts:42 | WARN | ui-test-manifest on androidTestImplementation | ../../setup/configuring-test-dependencies/SKILL.md |
| 2 | 1 setup | FeedTest.kt:18 | WARN | v1 createComposeRule import (deprecated) | ../../setup/choosing-test-rule-vs-runtest/SKILL.md |
| 3 | 2 finder | FeedTest.kt:34 | ERROR | onNodeWithText("Save") — no testTag in production | ../../finders/finding-nodes-by-tag-text-content/SKILL.md |
| 4 | 4 action | FeedTest.kt:51 | ERROR | performGesture { } — deprecated | ../../actions/injecting-touch-gestures/SKILL.md |
| 5 | 5 idle | FeedTest.kt:66 | ERROR | Thread.sleep(2000) before assertion | ../../synchronization/synchronizing-with-idle/SKILL.md |
| 6 | 5 idle | FeedTest.kt:88 | ERROR | autoAdvance not disabled before animation | ../../synchronization/testing-animations-deterministically/SKILL.md |
| 7 | 6 debug | FeedTest.kt:104 | NIT | assertExists with no printToLog on miss | ../../debug/printing-the-semantics-tree/SKILL.md |
重大度(次の 3 つをそのまま使います)。
- ERROR — テストが壊れている、不安定である、または誤った内容をアサートしています。マージ前に修正してください。
- WARN — テストは実行されますが、不安定さやリグレッションにつながる問題を含んでいます。簡単に直せる場合は、今回のイテレーションで修正してください。
- NIT — スタイルや保守性に関する問題です。関連するコードに手を入れるときに修正してください。
自動修正はしないでください。レポートをユーザーに渡し、修正はユーザー(または誘導先のスキルを後続で実行すること)に委ねてください。
パターン
パターン:影響範囲の大きさに基づいて指摘事項の優先順位を付ける
同じ *Test.kt に複数の指摘事項がある場合は、次の優先順位で対応します。
- まずフェーズ 1 のセットアップ上の阻害要因に対応します。 テストが誤ったソースセットにある場合や、異なるサーフェスが混在している場合、動作は未定義になります。その状態でフェーズ 5 のアイドルに関する問題を直しても、労力が無駄になります。
- フェーズ 4 のアクションより先に、フェーズ 5 のアイドルに関する問題に対応します。
Thread.sleepでIdlingResourceの不足を隠していると、フェーズ 4 のアクションに関する問題が見えなくなります。アイドル状態が適切になれば、アクションのタイミングに関する問題がはっきりします。 - フェーズ 3 のアサーションより先に、フェーズ 2 のファインダーに関する問題に対応します。 ファインダーが誤ったノードを対象にしていると、その後のアサーションには意味がありません。
- フェーズ 6 のデバッグ出力は、常に最後に修正します。 診断はしやすくなりますが、正しさは変わりません。
パターン:最初に grep する、問題を見つけやすいコードの特徴
テストを行ごとに読む前に、次の grep を実行して、影響の大きい問題を洗い出します。
# Phase 1 — v1 imports (deprecated)
grep -RIn 'import androidx.compose.ui.test.junit4.createComposeRule' .
grep -RIn 'import androidx.compose.ui.test.runComposeUiTest' .
# Phase 1 — manifest dep on the wrong configuration
grep -RIn 'ui-test-manifest' build.gradle.kts settings.gradle.kts buildSrc/
# Phase 2 — finder usage ratio (skydoves hot take #1: tag-heavy is correct)
grep -RIcn 'onNodeWithTag\|onNodeWithText\|onNodeWithContentDescription' src/
# Phase 4 — deprecated gesture API
grep -RIn 'performGesture' src/
# Phase 5 — Thread.sleep smell
grep -RIn 'Thread.sleep' src/
# Phase 5 — animation tests missing autoAdvance = false
grep -RIn 'animateFloatAsState\|animateDpAsState\|animateColorAsState\|rememberInfiniteTransition' src/test src/androidTest
# Phase 5 — off-thread mutation pattern (heuristic — review hits manually)
grep -RIn '\.value = ' src/test src/androidTest | grep -v 'runOnIdle\|runOnUiThread'
これらの grep の出力により、通常の監査レポートの 60~80 パーセントは、最初にじっくり読み込む前に埋まります。
パターン:監査を中止して別のスキルに誘導する場合
フェーズ 1 でテストが誤ったソースセットにあること(例:スクリーンショットテストが src/test/ にあること)が分かった場合は、中止してください。フェーズ 2~6 は実行しないでください。テスト全体は src/androidTest/ に移動したときに書き直すことになるため、現状のテストを監査しても労力の無駄です。../../setup/setting-up-host-vs-device-tests/SKILL.md に誘導し、移動後に監査をやり直してください。
同様に、フェーズ 1 で runComposeUiTest { } ブロックが @get:Rule createComposeRule() と同じクラス内にあることが分かった場合は、そこで中止し、../../setup/choosing-test-rule-vs-runtest/SKILL.md に誘導してください。環境が混在しているため、それ以降の指摘事項はすべて曖昧になります。
パターン:監査結果をユーザーに提示する
監査の最後に、短い文章の要約を書いてからテーブルを示します。要約では、重要度の高い上位 3 件と、次に実行すべき単一の関連スキルを示します。例:
The FeedTest.kt suite has 7 findings. The two ERRORs that block correctness are
(1) a Thread.sleep(2000) before the search assertion (FeedTest.kt:66) and
(2) an animation test without mainClock.autoAdvance = false (FeedTest.kt:88).
Run ../../synchronization/testing-animations-deterministically/SKILL.md first;
the autoAdvance fix typically resolves the Thread.sleep finding by exposing
a mainClock.advanceTimeBy(durationMs) replacement.
必須ルール
- MUST NOT 監査中にコードを変更してはいけません。監査では指摘事項を提示し、修正は振り分け先の兄弟スキルが適用します。
- MUST 6つのフェーズを順番どおりに実行してください。前のフェーズで修正が行われると後のフェーズの指摘事項は無効になるため、この順序により無駄な作業を最小限に抑えます。
- MUST すべての指摘事項を、単一の兄弟スキルに振り分けてください。振り分け先のスキルがない指摘事項は実行可能ではないため、レポートから除外してください。
- MUST スクリーンショット/RenderThread のコンテキスト以外にあるすべての
Thread.sleepを ERROR として指摘してください。Skydoves の辛口コメント #7。 - MUST
mainClock.autoAdvance = falseを設定していないすべてのアニメーションテストを ERROR として指摘してください。Skydoves の辛口コメント #3。 - MUST すべての v1 エントリーポイント(
androidx.compose.ui.test.junit4.createComposeRule、androidx.compose.ui.test.runComposeUiTest)を WARN として指摘してください。Skydoves の辛口コメント #6。 - MUST すべての
performGesture { }の使用を ERROR として指摘してください。この API は@Deprecatedであり、SPEC では推奨が禁止されています。 - MUST NOT 指摘事項を捏造してはいけません。あるフェーズで何も見つからなかった場合は、「Phase N: no findings」と記載してください。誤検知の指摘事項は監査の有用性を損ないます。
- MUST 監査レポートには、後続のスキルが出力を解析できるよう、表形式(Phase、File:line、Severity、Finding、Routed skill)を使用してください。
- PREFERRED: 「CI でテストが不安定になる」など、複数の指摘事項が1つの症状に集中している場合は、説明文の概要でその症状を示し、振り分け先の兄弟スキルが最初に表示されるよう表の順序を調整してください。
検証
- すべての監査フェーズが実行され、それぞれで指摘事項または「no findings」が出力されている。
- すべての指摘事項に Severity(ERROR | WARN | NIT)と振り分け先の兄弟スキルのパスがある。
- 監査自体によって、レビュー対象のテストファイル内のコードが変更されていない。
- Phase 1 の grep セットが実行され、その出力が表に反映されている。
- 監査レポートの表が有効な Markdown として出力されている(ユーザーが PR に貼り付けられる)。
- Phase 1 でセットアップ上のブロッカーが発生した場合(ソースセットの誤り、サーフェスの混在など)、Phase 2〜6 はスキップされ、振り分け先を示すメモを添えて監査が中止されている。
参考資料
- Compose テストの概要(Android Developers):https://developer.android.com/develop/ui/compose/testing
- Compose テストのチートシート:https://developer.android.com/develop/ui/compose/testing-cheatsheet
- Compose テストのセットアップ:https://developer.android.com/develop/ui/compose/testing#setup
- アニメーションのテスト:https://developer.android.com/develop/ui/compose/animation/testing
- Compose のセマンティクス:https://developer.android.com/develop/ui/compose/accessibility/semantics
- Compose UI のリリースノート:https://developer.android.com/jetpack/androidx/releases/compose-ui
- 関連するセットアップスキル:
../../setup/configuring-test-dependencies/SKILL.md、../../setup/choosing-test-rule-vs-runtest/SKILL.md、../../setup/setting-up-host-vs-device-tests/SKILL.md。 - 関連する検索スキル:
../../finders/finding-nodes-by-tag-text-content/SKILL.md、../../finders/composing-semantics-matchers/SKILL.md、../../finders/traversing-the-semantics-tree/SKILL.md。 - 関連するアサーションスキル:
../../assertions/asserting-node-state-and-text/SKILL.md、../../assertions/asserting-bounds-and-dimensions/SKILL.md。 - 関連するアクションスキル:
../../actions/clicking-and-scrolling/SKILL.md、../../actions/injecting-touch-gestures/SKILL.md、../../actions/injecting-mouse-and-keyboard/SKILL.md、../../actions/entering-text/SKILL.md。 - 関連する同期スキル:
../../synchronization/controlling-the-test-clock/SKILL.md、../../synchronization/testing-animations-deterministically/SKILL.md、../../synchronization/synchronizing-with-idle/SKILL.md。 - 関連するパターンスキル:
../../patterns/structuring-a-compose-test/SKILL.md、../../patterns/testing-lazy-lists/SKILL.md、../../patterns/testing-state-restoration/SKILL.md。 - 関連する相互運用スキル:
../../interop/testing-with-espresso-interop/SKILL.md。 - 関連するデバッグスキル:
../../debug/printing-the-semantics-tree/SKILL.md、../../debug/enabling-accessibility-checks/SKILL.md。 - skydoves — compose-performance-skills(本番環境側の監査に関する関連リポジトリ):https://github.com/skydoves/compose-performance-skills。