Skip to content

Write & Run Screenshot Tests

akshay-at-yml edited this page Aug 25, 2022 · 16 revisions

Shot and Showkase

Writing shot tests and using showkase in test classes are explained in the individual sections. This section will briefly show how to combine them with the below two appraoches.

Showkase Generated Tests.

In this approach, test class will implement ShowkaseScreenshotTest interface.
The test class must be abstract, and must be annotated with the @ShowkaseScreenshot as shown below. Showkase will autogenerate tests for each of the Previews / Colors / Typography available in the shoskase browser.

onScreenshot of ShowkaseScreenshotTest will provide a bitmap for each of the component in the showkase browser, which is then recorded or compared using Shot's compareScreenshot method.

@ShowkaseScreenshot(rootShowkaseClass = DesignModule::class)
abstract class DesignTests : ShowkaseScreenshotTest, ScreenshotTest {
    @get:Rule
    override val composeTestRule: ComposeContentTestRule = createComposeRule()

    override fun onScreenshot(
        id: String,
        name: String,
        group: String,
        styleName: String?,
        screenshotType: ShowkaseScreenshotType,
        screenshotBitmap: Bitmap
    ) {
        compareScreenshot(screenshotBitmap, "${group}_${name}")
    }
}

Using Showkase Metadata

In the above approach if we want to run tests for dark theme / light theme or different locales, different emulators must be instantiated, and screenshots for each of them must be saved in different directories. Reason, the tests are autogenerated and can not be modified.

In such cases this approach would be helpful, which will allow you to run tests on multiple configurations, but single emulator. Refer this file for more info

@RunWith(TestParameterInjector::class)
class ShotTests : ScreenshotTest {

    object Previews : TestParameter.TestParameterValuesProvider {
        override fun provideValues(): List<ComponentPreview> =
            Showkase.getMetadata().componentList.map(::ComponentPreview)
    }

    @Test
    fun tests(
        @TestParameter(valuesProvider = Previews::class)
        componentPreview: ComponentPreview
        @TestParameter(value = ["light", "dark"])
        uiMode: String
    ) {
       
        composeTestRule.setContent {
            CompositionLocalProvider(LocalConfiguration provides LocalConfiguration.current.apply {
                this.uiMode = if (uiMode == "dark") 
                                Configuration.UI_MODE_NIGHT_YES
                              else Configuration.UI_MODE_NIGHT_NO
            }) {
                componentPreview.content()
            }
        }
        // Use the shot method to record the compose 
        compareScreenshot(
            composeTestRule,
            screenshotName(componentPreview.toString(), locale, uiMode) // This is a name for screenshot
        )
    }
.....

Paparazzi and Showkase

Clone this wiki locally