Roborazziで最初にスクリーンショットを撮る時、詰まったポイント

# Roborazziとは
スクリーンショットテストを行うライブラリです。Robolectricと互換性があり、画面変更差分の出力や、gif画像の生成なども行うことができます。
https://github.com/takahirom/roborazzi

# 環境設定

この記事で扱う環境は以下の通りです：

- Android Studio: Android Studio Iguana 2023.2.1
- Android Gradle Plugin: 8.3.0
- Gradle: 8.4
- Robolectric: 4.11.1
- Roborazzi: 1.11.0
- Junit4: 1.6.6

# 導入
モジュールのGradleにrobolectricとroborazziのimplementationを追加します

    // roboletric
    testImplementation(libs.robolectric)

    // roborazzi
    testImplementation(libs.roborazzi)
    testImplementation(libs.roborazzi.compose)
    testImplementation(libs.roborazzi.rule)

    // createComposeRuleを使うために追加します
    testImplementation(libs.ui.test.junit4)

さらにpluginを追加します

    plugins {
        // roborazzi
        alias(libs.plugins.roborazzi)
    }

では、新規プロジェクトを作成した時に作られるGreetingのスクリーンショットを撮ってみたいと思います。

```Kotlin
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}
```
```Kotlin
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import com.github.takahirom.roborazzi.captureRoboImage
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.GraphicsMode

@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
class MainActivityTest {
    @get:Rule
    val composeRule = createComposeRule()

    @Test
    fun greetingTest() {
        composeRule.setContent {
            Greeting(name = "Robolectric")
        }

        composeRule
            .onRoot()
            .captureRoboImage()
    }
}
```

コマンドでテストを実行します。

     ./gradlew recordRoborazziDebug

すると、テストが失敗しました

    > Task :app:testDebugUnitTest FAILED

    FAILURE: Build failed with an exception.

詳細なエラーログを見てみます

    java.lang.RuntimeException: Unable to resolve activity for Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=org.robolectric.default/androidx.activity.ComponentActivity } -- see https://github.com/robolectric/robolectric/pull/4736 for details
    	at org.robolectric.android.internal.RoboMonitoringInstrumentation.startActivitySyncInternal(RoboMonitoringInstrumentation.java:105)
    	at org.robolectric.android.internal.LocalActivityInvoker.startActivity(LocalActivityInvoker.java:36)
    	at org.robolectric.android.internal.LocalActivityInvoker.startActivity(LocalActivityInvoker.java:41)
    	at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:362)
    	at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:202)
    	at androidx.test.ext.junit.rules.ActivityScenarioRule.lambda$new$0(ActivityScenarioRule.java:77)
    	at androidx.test.ext.junit.rules.ActivityScenarioRule$$ExternalSyntheticLambda1.get(D8$$SyntheticClass)
    	at androidx.test.ext.junit.rules.ActivityScenarioRule.before(ActivityScenarioRule.java:110)
    	at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:50)
    	at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(AndroidComposeTestRule.android.kt:272)
    	at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(AndroidComposeTestRule.android.kt:271)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.withDisposableContent(ComposeUiTest.android.kt:495)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1$1.invoke(ComposeUiTest.android.kt:327)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withComposeIdlingResource(ComposeUiTest.android.kt:379)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withComposeIdlingResource(ComposeUiTest.android.kt:230)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1.invoke(ComposeUiTest.android.kt:326)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withWindowRecomposer(ComposeUiTest.android.kt:353)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withWindowRecomposer(ComposeUiTest.android.kt:230)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1.invoke(ComposeUiTest.android.kt:325)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withTestCoroutines(ComposeUiTest.android.kt:366)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withTestCoroutines(ComposeUiTest.android.kt:230)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1.invoke(ComposeUiTest.android.kt:324)
    	at androidx.compose.ui.test.junit4.IdlingStrategy.withStrategy(IdlingStrategy.android.kt:52)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invoke(ComposeUiTest.android.kt:323)
    	at androidx.compose.ui.test.junit4.IdlingResourceRegistry.withRegistry(IdlingResourceRegistry.jvm.kt:157)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1.invoke(ComposeUiTest.android.kt:322)
    	at androidx.compose.ui.test.junit4.ComposeRootRegistry.withRegistry(ComposeRootRegistry.android.kt:146)
    	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.runTest(ComposeUiTest.android.kt:321)
    	at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1.evaluate(AndroidComposeTestRule.android.kt:271)
    	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    	at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:588)
    	at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$2(SandboxTestRunner.java:290)
    	at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:101)
    	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    	at java.base/java.lang.Thread.run(Thread.java:840)

一行目のエラーログを読むに、どうやらアクティビティの起動ができずRuntimeExceptionを返されてしまったようです。

調べてみると、モジュールのgradleにこの記述を足すことで、robolectricがマニフェストで定義されたアクティビティにアクセスできるようで、スクリーンショットを実行することができるようになりました。

    android {
        ...
        testOptions {
            unitTests {
                includeAndroidResources = true
            }
        }
    }

![スクリーンショット 2024-04-25 22.44.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524029/b280bce3-abb0-f2c5-b915-1469ec93b9fe.png)

![com.example.usingscreenshot.MainActivityTest.greetingTest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524029/c545f98b-390a-9bc9-686d-69a839b7c48f.png)


# 参考
https://stackoverflow.com/questions/55635528/unable-to-resolve-activity-for-intent-robolectric-activityscenariorule