Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Roborazziを最大限に活用する(導入編)
Search
Swimmy
December 01, 2023
0
270
Roborazziを最大限に活用する(導入編)
12/1のDroidKaigi.collect { #7@TOkyo } で登壇した資料です
Swimmy
December 01, 2023
Tweet
Share
More Decks by Swimmy
See All by Swimmy
違いがワカルKotlinプログラマーへの道
reoandroider
0
130
違いのワカル Kotlinプログラマーへの道
reoandroider
0
200
[Jetpack Compose] 原理から見るSkippable対応
reoandroider
1
300
Androdアプリ開発におけるネストスクロール問題と向き合うの説明用途
reoandroider
0
2.5k
Androdアプリ開発におけるネストスクロール問題と向き合うの説明用途
reoandroider
0
2.3k
Androdアプリ開発におけるネストスクロール問題と向き合うの説明用途~NestedScrollInteropConnectionは何してるの?編~
reoandroider
0
2.2k
Master of NestedScroll
reoandroider
0
12k
Jetpack_Composeで_半円のプログレスバーを作った話
reoandroider
0
370
Compose「急いで」キャッチアップする
reoandroider
0
21
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.8k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.5k
Building Applications with DynamoDB
mza
93
6.2k
Practical Orchestrator
shlominoach
186
10k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.4k
A Modern Web Designer's Workflow
chriscoyier
693
190k
What's in a price? How to price your products and services
michaelherold
244
12k
Why Our Code Smells
bkeepers
PRO
335
57k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.3k
Testing 201, or: Great Expectations
jmmastey
41
7.2k
Rails Girls Zürich Keynote
gr2m
94
13k
Automating Front-end Workflow
addyosmani
1367
200k
Transcript
Harada Reo @ すいみー DroidKaigi @Tokyo .collect {} Roborazziを最大限に活用する (導入編)
すいみー CyberAgent Inc. Ameba どすこい塾 DroidKaigi Staff RunningReo(X) 自己紹介 /
Introduction
このLTのゴール 聞いてくれた人が Roborazziを スムーズに導入できる状態
Roborazzi Roborazziとは? takahiromさんによる 静的なスクリーンショットテストライブラリ https://github.com/takahirom/roborazzi
目次 / Index プロダクトが抱えている課題 2 3 今後の展望 1 Roborazzi導入手順
プロダクトが抱えている課題 1
紹介 Ameba ブログや話題の芸能ニュースを毎日お届け! https://play.google.com/store/apps/details?id=jp.ameba&hl=ja&gl=US
紹介 リリースから10年以上運用している
紹介 Amebaでは Roborazziを 導入中・・・
課題点 アプリの画面数が多く QCさんによる デグレ確認のテスト項目が 膨大な量になっている
解決アプローチ Roborazziを用いることで 目視確認を自動化して 品質担保を目指す
Roborazzi導入手順 2
前提の話 ・Hilt対応していると楽 ・Jetpack ComposeもAndroidViewも 相互運用も対応しているよ
前提の話 ・Hilt対応していると楽 ・Jetpack ComposeもAndroidViewも 相互運用も対応しているよ
前提の話 ・Hilt対応していると楽 ・Jetpack ComposeもAndroidViewも 相互運用も対応しているよ Activityをベースにテストする時にテスト用のApplicationクラスを Robolectricに登録するなど冗長的な作業が発生する
前提の話 ・Hilt対応していると楽 ・Jetpack ComposeもAndroidViewも 相互運用も対応しているよ
前提の話 ・Hilt対応していると楽 ・Jetpack ComposeもAndroidViewも 相互運用も対応しているよ ComposeRuleが内部でActivityScenarioを用いているため // 内部実装 inline fun
<reified A : ComponentActivity> createAndroidComposeRule(): AndroidComposeTestRule<ActivityScenarioRule<A>, A> { return createAndroidComposeRule(A::class.java) }
依存関係の追加 // root build.gradle buildScript { dependencies { classPath =
"io.github.takahirom.roborazzi:roborazzi-gradle-plugin: [version]" } }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
依存関係の追加 // module build.gradle apply plugin: "io.github.takahirom.roborazzi" android { testOptions
{ unitTests { includeAndroidResources = true } } } dependencies { testImplementation "androidx.test.ext:junit-ktx:[version]" testImplementation "org.robolectric:robolectric:[4.10-alpha以上]" testImplementation "io.github.takahirom.roborazzi:roborazzi:[version]" testImplementation "androidx.compose.ui:ui-test-junit4:[version]" }
テストクラス作成 @RunWith(AndroidJUnit4::class) @GraphicsMode(GraphicsMode.Mode.NATIVE) class BookmarkScreenShotTest { ...
テストクラス作成 @RunWith(AndroidJUnit4::class) @GraphicsMode(GraphicsMode.Mode.NATIVE) class BookmarkScreenShotTest { ...Robolectric4.10-alphaから使える実装 ネイティブのグラフィックをサポート
テストクラス作成 ... class BookmarkScreenShotTest { @get:Rule(order = 1) val addActivityToRobolectricRule
= object : TestWatcher() { override fun starting(description: Description?) { super.starting(description) val appContext: Application = ApplicationProvider.getApplicationContext() val activityInfo = ActivityInfo().apply { name = ComponentActivity::class.java.name packageName = appContext.packageName } shadowOf(appContext.packageManager).addOrUpdateActivity(activityInfo) } }
テストクラス作成 ... class BookmarkScreenShotTest { @get:Rule(order = 1) val addActivityToRobolectricRule
= object : TestWatcher() { override fun starting(description: Description?) { super.starting(description) val appContext: Application = ApplicationProvider.getApplicationContext() val activityInfo = ActivityInfo().apply { name = ComponentActivity::class.java.name packageName = appContext.packageName } shadowOf(appContext.packageManager).addOrUpdateActivity(activityInfo) } } RobolectricへのActivityの登録を行う
テストクラス作成 ... class BookmarkScreenShotTest { @get:Rule(order = 1) val addActivityToRobolectricRule
= object : TestWatcher() { override fun starting(description: Description?) { super.starting(description) val appContext: Application = ApplicationProvider.getApplicationContext() val activityInfo = ActivityInfo().apply { name = ComponentActivity::class.java.name packageName = appContext.packageName } shadowOf(appContext.packageManager).addOrUpdateActivity(activityInfo) } } 登録できてないとエラーが発生する java.lang.RuntimeException: Unable to resolve activity for Intent...
テストクラス作成 ... class BookmarkScreenShotTest { ... @get:Rule(order = 2) val
composeRule = createComposeRule() @Test @Config(sdk = [33], qualifiers = RobolectricDeviceQualifiers.Pixel7) fun captureSampleScreen() { composeRule.setContent { SampleTheme { SampleScreen(...) } } composeRule.onNode(isRoot()).captureRoboImage() }
テストクラス作成 ... class BookmarkScreenShotTest { ... @get:Rule(order = 2) val
composeRule = createComposeRule() @Test @Config(sdk = [33], qualifiers = RobolectricDeviceQualifiers.Pixel7) fun captureSampleScreen() { composeRule.setContent { SampleTheme { SampleScreen(...) } } composeRule.onNode(isRoot()).captureRoboImage() } createComopseRuleを呼び出す
テストクラス作成 ... class BookmarkScreenShotTest { ... @get:Rule(order = 2) val
composeRule = createComposeRule() @Test @Config(sdk = [33], qualifiers = RobolectricDeviceQualifiers.Pixel7) fun captureSampleScreen() { composeRule.setContent { SampleTheme { SampleScreen(...) } } composeRule.onNode(isRoot()).captureRoboImage() } スクショする端末のSDKと機種を指定
テストクラス作成 ... class BookmarkScreenShotTest { ... @get:Rule(order = 2) val
composeRule = createComposeRule() @Test @Config(sdk = [33], qualifiers = RobolectricDeviceQualifiers.Pixel7) fun captureSampleScreen() { composeRule.setContent { SampleTheme { SampleScreen(...) } } composeRule.onNode(isRoot()).captureRoboImage() } Composeを起動させる
テストクラス作成 ... class BookmarkScreenShotTest { ... @get:Rule(order = 2) val
composeRule = createComposeRule() @Test @Config(sdk = [33], qualifiers = RobolectricDeviceQualifiers.Pixel7) fun captureSampleScreen() { composeRule.setContent { SampleTheme { SampleScreen(...) } } composeRule.onNode(isRoot()).captureRoboImage() } captureRoboImageでスクショを撮る
テスト実行 ./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト
./gradlew verifyAndRecordRoborazziDebug 差分があるかどうかとスクショを撮る
テスト実行 ./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト
./gradlew verifyAndRecordRoborazziDebug 差分があるかどうかとスクショを撮る
./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト ./gradlew
verifyAndRecordRoborazziDebug 差分があるかどうかとスクショを撮る テスト実行
./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト ./gradlew
verifyAndRecordRoborazziDebug 差分があるかどうかとスクショを撮る テスト実行
./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト ./gradlew
verifyAndRecordRoborazziDebug 差分があるかどうかとスクショを撮る テスト実行
./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト ./gradlew
verifyAndRecordRoborazziDebug 差分があるかどうかとスクショを撮る テスト実行
./gradlew recordRoborazziDebug 初期状態のスクショを撮る・比較におけるbefore ./gradlew compareRoborazziDebug 差分のスクショを撮る ./gradlew verifyRoborazziDebug 差分があるかどうかのテスト ./gradlew
verifyAndRecordRoborazziDebug 差分があるかどうかとある場合にスクショを撮る テスト実行
今後の展望 3
このLTのゴール 聞いてくれた人が Roborazziを スムーズに導入できる状態
まとめ 躓いて何日かハマったこともあったが 一度スクショ撮れるとあとは楽
まとめ 導入始めたばかりなので まだ検証したいことはある ・ベンチマークの設定 ・CIの時間への影響 ・UIテストとの兼ね合い
まとめ 品質担保において活用できるが エンジニアだけが使う ツールで消費されるのは もったいない気がする
まとめ デザイナーとのコミュニケーションを 円滑にする手段として活用したい (カタログやデザインシステムの準拠など)
まとめ 現状スクショのdiff詳細は見れないので OSSやEspressoのdump出力を活用して 最大限活用する方法を見つけていきたい
Harada Reo @ すいみー Roborazziを最大限に活かす (運用編)
to be continued