Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
VRTをプロダクトに導入するまでのお話
Search
gotlin
May 09, 2024
370
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
VRTをプロダクトに導入するまでのお話
gotlin
May 09, 2024
More Decks by gotlin
See All by gotlin
KotlinConf2025現地参加 と Compose HotReload導入記
goutarouh
0
45
Applicationクラスのライフサイクルに気をつけよう
goutarouh
0
88
Conference-app-2024の良さげな実装を勝手にいくつか紹介する
goutarouh
0
94
Drag & Drop in LazyColumn
goutarouh
0
970
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
96
14k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
580
Building the Perfect Custom Keyboard
takai
2
900
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
320
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
270
Leo the Paperboy
mayatellez
10
2.4k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
260
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
540
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
350
Transcript
@gotlinan 2024/05/07 (⽕) DroidKaigi.collect { #8@Tokyo } VRTをプロダクトに 導⼊するまでのお話
所属: KINTOテクノロジーズ株式会社(通称KTC) モバイル開発グループ 開発: my route X(twitter): @gotlinan 趣味: バイク
my routeのVRT導⼊までの歴史 2024/4末~ 2023/11 2024/1 2023/12 2024/2 チーム内で VRT導⼊しちゃう〜? の声が出始める
Roborazziを 個⼈プロジェクト で導⼊ my routeでバグ発⽣ VRTがあれば 防げたかも。。。 my routeに 試験的に導⼊ とあるモジュールで実験 本格的実装 & 運⽤開始
Roborazzi導⼊に⾃信満々 2024/4末~ 2023/11 2024/1 2023/12 2024/2 チーム内で VRT導⼊しちゃう〜? の声が出始める Roborazziを
個⼈プロジェクト に導⼊ my routeでバグ発⽣ VRTがあれば 防げたかも。。。 my routeに 試験的に導⼊ とあるモジュールで実験 本格的実装 & 運⽤開始
Compose で動作確認 @RunWith(AndroidJUnit4::class) @GraphicsMode(GraphicsMode.Mode.NATIVE) class TestClass { @get:Rule val composeTestRule
= createComposeRule() @Test fun captureTestScreen() { composeTestRule.setContent { TestScreen(state = TEST_DATA) } composeTestRule.onRoot().captureRoboImage() } }
my routeの現在の構成 Activity Fragment A Fragment B xml (DataBinding) Compose
Compose xml (DataBinding)
Fragment × DataBinding × Hilt でVRTを⾏う必要がある
Fragment × DataBinding × Hilt で動作確認 @RunWith(AndroidJUnit4::class) @GraphicsMode(GraphicsMode.Mode.NATIVE) class TestClass
{ @Test fun captureTestFragment() { launchFragmentInContainer<TestFragment>() onView(withId(R.id.testFragment)).captureRoboImage() } }
Fragment × DataBinding × Hilt で動作確認 // https://issuetracker.google.com/issues/126775542 kaptTest("androidx.databinding:databinding-compiler:$version")
Fragment × DataBinding × Hilt で動作確認
Fragment × DataBinding × Hilt で動作確認 @AndroidEntryPoint class HiltTestActivity :
AppCompatActivity() https://github.com/android/architecture-samples/blob/dev- hilt/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/HiltExt.kt
Fragment × DataBinding × Hilt で動作確認 inline fun <reified T
: Fragment> launchFragmentInHiltContainer( fragmentArgs: Bundle? = null, crossinline action: Fragment.() -> Unit = {}, ) { val startActivityIntent = Intent.makeMainActivity(ComponentName( ApplicationProvider.getApplicationContext(), HiltTestActivity::class.java, )) ActivityScenario.launch<HiltTestActivity>(startActivityIntent).onActivity { val fragment = it.supportFragmentManager.fragmentFactory.instantiate( Preconditions.checkNotNull(T::class.java.classLoader), T::class.java.name, ) fragment.arguments = fragmentArgs it.supportFragmentManager.beginTransaction().apply { add(android.R.id.content, fragment, "") }. commitNow() fragment.action() } } https://github.com/android/architecture-samples/blob/dev- hilt/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/HiltExt.kt
@RunWith(AndroidJUnit4::class) @Config(application = HiltTestApplication::class) @HiltAndroidTest @GraphicsMode(GraphicsMode.Mode.NATIVE) class TestFragmentScreenShot { @get:Rule
var hiltRule = HiltAndroidRule(this) @Inject lateinit var xxxApi: XXXApi @Before fun setup() { hiltRule.inject() } @Test fun captureFragmentImage() { launchFragmentInHiltContainer<TestFragment> { onView(withId(R.id.testFragment)).captureRoboImage() } } } Fragment × DataBinding × Hilt で動作確認
@RunWith(AndroidJUnit4::class) @Config(application = HiltTestApplication::class) @HiltAndroidTest @GraphicsMode(GraphicsMode.Mode.NATIVE) class TestFragmentScreenShot { @get:Rule
var hiltRule = HiltAndroidRule(this) @Inject lateinit var xxxApi: XXXApi @Before fun setup() { hiltRule.inject() } @Test fun captureFragmentImage() { launchFragmentInHiltContainer<TestFragment> { onView(withId(R.id.testFragment)).captureRoboImage() } } } Fragment × DataBinding × Hilt で動作確認
@RunWith(AndroidJUnit4::class) @Config(application = HiltTestApplication::class) @HiltAndroidTest @GraphicsMode(GraphicsMode.Mode.NATIVE) class TestFragmentScreenShot { @get:Rule
var hiltRule = HiltAndroidRule(this) @Inject lateinit var xxxApi: XXXApi @Before fun setup() { hiltRule.inject() } @Test fun captureFragmentImage() { launchFragmentInHiltContainer<TestFragment> { onView(withId(R.id.testFragment)).captureRoboImage() } } } Fragment × DataBinding × Hilt で動作確認
⾊々な条件VRTできた! あとはプロジェクトに本格的に導⼊するだけ! ⼀⽇もあれば余裕だ!
…
テストが全然通らないぞ…? というかテストが終わらないぞ…?
[DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager]
Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. java.lang.NullPointerException thrown from thread "FlipperConnectionThread" [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. 以下永遠に続く……… 発⽣していたエラー
[DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager]
Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. java.lang.NullPointerException thrown from thread "FlipperConnectionThread" [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. 以下永遠に続く……… 発⽣していたエラー デッドロック的な…?
調べても全然解決できない🥺 きっとPCのスペックが⾜りないんだー! org.gradle.jvmargs=-Xmx4g gradle デーモン 再起動など ヒープ サイズ 拡⼤
よく⾒たら…
[DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager]
Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. java.lang.NullPointerException thrown from thread "FlipperConnectionThread" [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. [DefaultFileLockManager] Waiting to acquire shared lock on daemon addresse [DefaultFileLockManager] Lock acquired on daemon addresses registry. [DefaultFileLockManager] Releasing lock on daemon addresses registry. 以下永遠に続く……… 発⽣していたエラー (--debug オプションが必要) Flipper…?
・Flipperとはmy routeで使⽤しているデバッグツール ・Applicationクラスで設定 ・Applicationクラスを、Manifestファイルで指定 class MyrouteApplication : Application() { override
fun onCreate() { Flipper.initialize(this) ... } } Flipperについて <application android:name=".MyrouteApplication" /> </application>
Composeでテストを⾏うとき、起動するActivityの宣⾔があるManifestをマージする // build.gradle debugImplementation("androidx.compose.ui:ui-test-manifest:$version") <!-- app/build/merged-manifest/ --> <activity android:name="androidx.activity.ComponentActivity" android:exported="true"
/> 専⽤のActivityをManifestにマージする
// モジュールのbuild.gradle.kts android { testOptions { unitTests { isIncludeAndroidResources =
true } } } Roborazzi使うときに必要な設定 > Enables unit tests to use Android resources, assets, and manifests. https://developer.android.com/reference/tools/gradle-api/8.3/com/android/build/api/dsl/UnitTestOptions#isIncludeAndroidResou
@RunWith(AndroidJUnit4::class) @Config(application = Application::class) @GraphicsMode(GraphicsMode.Mode.NATIVE) class TestClass { } 対応⽅法
約半年後、 ようやく導⼊できました…!
教訓 ・エラー⽂はちゃんと読もう ・必要に応じて、./gradlew XXX --debug などを活⽤しよう ・何でdebugImplementationを使っているかを考えよう ・コードには理由がある(はず) ・やってないことに対して、すぐにできるでしょみたいに⾼を括らないようにしよう ・⾃分がやることにも他⼈がやることに対しても
ご清聴ありがとうございました!