Compose Preview Screenshot Testingで、通常のAndroidビルドでは正常なスタイルがCyclic style parent definitionsと判定され、スクリーンショットが1枚も生成されないことがあります。ドットを含むスタイル名に明示的なparent=""を指定した場合のリソース解決不具合で、GoogleはIssue #539672113として修正し、Android Studio Rabbit 1 Canary 3の修正一覧に掲載しています。
実際のエラー
com.android.tools.screenshot.ScreenshotRenderException:
Screenshot rendering failed:
Render Problems:
- Cyclic style parent definitions:
"Modal" specifies parent "Modal.Base" implies parent "Modal"
- Too many errors (457 more errors not displayed)
HTMLレポートではReference Image、Diff Image、New Imageが空欄になるだけで、原因が表示されない場合があります。詳細は次のJUnit XMLにある<error>を確認します。
module/build/test-results/validate<Variant>ScreenshotTest/
TEST-preview-screenshot-test-engine.xml
原因
Androidのスタイル名にドットがある場合、parent属性を省略するとドットより前の名前が暗黙の親として解釈されます。一方、parent=""を明示すると「親を持たず、暗黙の親も推測しない」という有効な定義になります。
<style name="Modal.Base" parent="">
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="Modal" parent="Modal.Base" />
AAPT2と通常のアプリビルドはこの定義を正しく処理します。しかし影響版のPreview Screenshot Testingでは、マージ済みリソースからレンダラーへ渡す途中で「空のparent」と「parent属性なし」の区別が失われます。その結果、Modal.Baseの暗黙の親をModalと誤推測し、Modal → Modal.Base → Modalという存在しない循環を報告します。
対象:Compose Preview Screenshot Testingを使い、AARまたはモジュール内にドット付きスタイル名とparent=""が存在するプロジェクト
確認された影響版:screenshot-validation-api/screenshot-validation-junit-engine 0.0.1-alpha15、0.0.1-alpha16
公式修正掲載:Android Studio Rabbit 1 | 2026.2.1 Canary 3
推奨する解決方法
1. Rabbit 1 Canary 3以降へ更新する
Googleの修正が掲載されたAndroid Studio Rabbit 1 Canary 3以降へ更新し、対応するCompose Screenshot Testingコンポーネントを使用します。プレビュー版を導入する場合は、既存のスクリーンショット基準画像やCI結果が変化しないか、別ブランチで確認してください。
2. 更新できない場合はドットのない中間スタイルを置く
公式Issueで確認された回避策は、空のparentを使わず、ドットを含まない空のスタイルを明示的な親にする方法です。
<style name="ModalNoParent" />
<style name="Modal.Base" parent="@style/ModalNoParent">
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="Modal" parent="Modal.Base" />
非空の親名がレンダラーまで保持されるため、ドットによる暗黙の親推測を回避できます。これは影響版向けの暫定策であり、ライブラリの公開APIやテーマ継承への影響を確認してから適用してください。
発生箇所の確認手順
validate<Variant>ScreenshotTestまたはscreenshotTest<Variant>を実行します。- HTMLレポートで画像セルがすべて空か確認します。
- JUnit XMLを開き、
ScreenshotRenderExceptionとCyclic style parent definitionsを検索します。 - マージ済みリソースの
merger.xmlで、該当スタイルにparent=""が残っているか確認します。 - アプリ自体のビルドと実行が正常なら、アプリのテーマ循環ではなくレンダラーの誤検出である可能性が高いと判断できます。
./gradlew :module:validateDebugScreenshotTest --stacktrace
grep -R "Cyclic style parent definitions" module/build/test-results/validateDebugScreenshotTest
代替策
- 該当AARを管理している場合は、中間スタイルによる回避版を一時的に提供します。
- 外部ライブラリ由来なら、依存関係を直接書き換えず、修正版ツールへの更新を優先します。
- CIを止められない場合は影響プレビューのみ一時除外できますが、描画回帰を検出できなくなるため対象と期限を記録してください。
修正確認
./gradlew :module:updateDebugScreenshotTest
./gradlew :module:validateDebugScreenshotTest
検証タスクが成功することに加え、HTMLレポートにReference/Diff/New Imageが表示されること、JUnit XMLから循環エラーが消えること、通常のアプリでテーマ表示が変わっていないことを確認します。
注意点
parent=""は誤ったXMLではありません。通常ビルドが成功している場合、機械的に削除すると暗黙の親推測が有効になり、本物の継承変更を起こす可能性があります。- エラー行が大量に繰り返されても、複数の循環があるとは限りません。1つのリソース解決失敗が各プレビューで反復される場合があります。
- Rabbit 1 Canary 3はプレビュー版です。安定版への取り込み状況は、採用する版の公式修正一覧で確認してください。
まとめ
Cyclic style parent definitions: "Modal" specifies parent "Modal.Base" implies parent "Modal"は、ドット付きスタイルの明示的なparent=""をScreenshot Testingのレンダラーが保持できないことで起きる誤検出です。推奨対応はRabbit 1 Canary 3以降への更新です。更新までの暫定策として、ドットのない空スタイルを明示的な親にすると誤った暗黙継承を避けられます。
