{"id":62366,"date":"2024-06-26T09:57:59","date_gmt":"2024-06-26T04:27:59","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=62366"},"modified":"2024-06-28T16:18:17","modified_gmt":"2024-06-28T10:48:17","slug":"screenshot-testing-with-jetpack-compose","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/screenshot-testing-with-jetpack-compose\/","title":{"rendered":"Screenshot testing with jetpack compose"},"content":{"rendered":"<h2>What is Screenshot testing<\/h2>\n<p>Screenshot or snapshot testing is a way to automate the validation of the UI components and widgets. It prevents regressions when updating any existing screen or component. A screenshot testing tool helps render a piece of UI (a screen or component), takes a snapshot of it, and then compares it with the existing correct snapshot. If the image doesn\u2019t match, then the test is failed, alerting the developer that something visually has changed. Screenshot tests can be easily integrated with the CI server to run on every build or PR.<\/p>\n<blockquote><p>NOTE: One thing to understand here is that screenshot testing is just another type of unit testing to make sure your code changes work fine. It does not replace any existing UI testing methodology.<\/p><\/blockquote>\n<p>To put things in perspective, below is a demonstration of how a screenshot test works.<\/p>\n<blockquote>\n<div id=\"attachment_62536\" style=\"width: 831px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-62536\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-62536 \" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/06\/context.png\" alt=\"Screenshot test report(test failed) \" width=\"821\" height=\"593\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/06\/context.png 911w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/context-300x217.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/context-768x555.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/context-624x451.png 624w\" sizes=\"(max-width: 821px) 100vw, 821px\" \/><p id=\"caption-attachment-62536\" class=\"wp-caption-text\">Screenshot test report (test failed)<\/p><\/div>\n<p>&nbsp;<\/p><\/blockquote>\n<p>The reference image here is the correct one against which the latest UI design (actual image) is compared, and the diff image shows the differences between the two screenshots (reference and actual).<br \/>\nThe test report above shows the test failed because the LoginButton&#8217;s radius in the actual image is not the same as the reference image, and the diff image highlights the same.<\/p>\n<p>That&#8217;s all for the introduction. Now we will dive into the Compose Preview Screenshot Testing tool and learn how we can use it in our project to create and run screenshot tests.<\/p>\n<blockquote>\n<hr \/>\n<\/blockquote>\n<h2>Compose Preview Screenshot Testing<\/h2>\n<p>Compose Preview Screenshot Testing tool is recently released in alpha, it is designed to be as easy to use as composable previews.<\/p>\n<p>To use Compose Preview Screenshot Testing, we need to use following:-<br \/>\n<code>Android Gradle 8.5.0-beta01<\/code> or later.<br \/>\n<code>Kotlin 1.9.20<\/code> or later<\/p>\n<h2>Setup<\/h2>\n<p><strong>1.\u00a0<\/strong> Add the <code>com.android.compose.screenshot<\/code> plugin and <code>ui-tooling<\/code> dependency to your project.<\/p>\n<pre><code>\r\n [versions]\r\n agp = \"8.5.0-beta01\"\r\n kotlin = \"1.9.20\"\r\n screenshot = \"0.0.1-alpha01\"\r\n [plugins]\r\n screenshot = { id = \"com.android.compose.screenshot\", version.ref = \"screenshot\"}\r\n ...\r\n [libraries]\r\n androidx-compose-ui-tooling = { group = \"androidx.compose.ui\", name = \"ui-tooling\"}\r\n<\/code><\/pre>\n<p>In the module level gradle file add plugin and dependency:-<\/p>\n<pre><code>\r\n plugins {\r\n   alias(libs.plugins.screenshot)\r\n  }<\/code><\/pre>\n<pre><code>\r\n  dependencies {\r\n    screenshotTestImplementation(libs.androidx.compose.ui.tooling)\r\n   }<\/code><\/pre>\n<p><strong>2.<\/strong> Next, we have to enable the experimental property for screenshot test in project&#8217;s <code>gradle.properties<\/code> file.<\/p>\n<pre><code>android.experimental.enableScreenshotTest=true<\/code><\/pre>\n<p><strong>3.<\/strong> In android {} block of your module-level <code>build.gradle.kts<\/code> file, enable the experimental flag to use the <code>screenshotTest<\/code> source set and ensure that <code>kotlinCompilerExtensionVersion<\/code> is set to 1.5.4 or later.<\/p>\n<pre><code>\r\n android {\r\n ...\r\n composeOptions {\r\n kotlinCompilerExtensionVersion = \"1.5.4\"\r\n }\r\n experimentalProperties[\"android.experimental.enableScreenshotTest\"] = true\r\n}<\/code><\/pre>\n<hr \/>\n<h2 id=\"generate-reference-images\" role=\"presentation\" data-text=\"Generate reference images\"><span class=\"devsite-heading\" role=\"heading\">Creating a screenshot test<br \/>\n<\/span><\/h2>\n<p>With this, setup is all done, and we are ready to create our first screenshot test. For simplicity, we will use a simple widget to perform the test. We will be creating a button Composable only, and we will change its border radius and horizontal padding to break the test and visualize the test result.<br \/>\nBelow is the composable we will be testing:<\/p>\n<pre>@Composable\r\nfun PrimaryButton( title:String){\r\n   Button(\r\n     modifier = Modifier.fillMaxWidth(),\r\n     onClick = {},\r\n     shape = RoundedCornerShape(20.dp),\r\n     ) {\r\n        Text(title)\r\n       }\r\n }<\/pre>\n<p>&nbsp;<\/p>\n<p>Next step is to create a screenshot test for our composable. First we need to create a new sourceset, named <code>screenshotTest<\/code> inside <code>src<\/code>, and create a new test file under it.<\/p>\n<div id=\"attachment_62537\" style=\"width: 860px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-62537\" decoding=\"async\" loading=\"lazy\" class=\" wp-image-62537\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/06\/4.png\" alt=\"Screenshot test sourceset\" width=\"850\" height=\"478\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/06\/4.png 952w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/4-300x169.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/4-768x432.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/4-624x351.png 624w\" sizes=\"(max-width: 850px) 100vw, 850px\" \/><p id=\"caption-attachment-62537\" class=\"wp-caption-text\">Screenshot test source set<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>Now we will create our test case for <code>PrimaryButton<\/code> Composable. Compose Preview Screenshot Testing is designed to be used as easily as a composable preview. We can also use <code>@Preview<\/code> parameters, such as <code>uiMode<\/code> or <code>fontScale<\/code>, and more to help us scale our tests.<\/p>\n<pre>class PrimaryButtonScreenshotTest {\r\n@Preview(showBackground = true)\r\n@Composable\r\nfun PrimaryButtonPreview() {\r\n   MaterialTheme {\r\n     PrimaryButton(\"Login\")\r\n     }\r\n   }\r\n}<\/pre>\n<h2><\/h2>\n<h2>Generating reference screenshot<\/h2>\n<p>Now that we have our test in place, we will generate a screenshot for our preview. This screenshot will be later used to compare with the new one when we make changes to our composable. To generate a screenshot, we have to run the command below.<\/p>\n<p><code>.\/gradlew updateDebugScreenshotTest<\/code><\/p>\n<p>After running this command you can see that a png image is generated under the same screenshot source set inside the reference directory.<\/p>\n<div id=\"attachment_62539\" style=\"width: 830px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-62539\" decoding=\"async\" loading=\"lazy\" class=\" wp-image-62539\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/06\/1-1.png\" alt=\"Generated reference image\" width=\"820\" height=\"387\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/06\/1-1.png 1076w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/1-1-300x142.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/1-1-1024x483.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/1-1-768x363.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/1-1-624x295.png 624w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><p id=\"caption-attachment-62539\" class=\"wp-caption-text\">Generated reference image<\/p><\/div>\n<h2><\/h2>\n<h2>Validating screenshot for test<\/h2>\n<p>Now that our reference image is generated, we can validate our current implementation of composable against it.<br \/>\nwe need to run the following command to validate:-<\/p>\n<p><code>.\/gradlew validateDebugScreenshotTest<\/code><\/p>\n<p>After running this command we can check the test status in the console and also get the generated report. The generated HTML report can be found at <code>{module}\/build\/reports\/screenshotTest\/preview\/{variant}\/index.html<\/code><\/p>\n<div id=\"attachment_62540\" style=\"width: 833px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-62540\" decoding=\"async\" loading=\"lazy\" class=\" wp-image-62540\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/06\/2.png\" alt=\"Test successful (build\/reports\/screenshotTest\/preview\/index.html)\" width=\"823\" height=\"382\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/06\/2.png 1287w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/2-300x139.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/2-1024x475.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/2-768x356.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/2-624x289.png 624w\" sizes=\"(max-width: 823px) 100vw, 823px\" \/><p id=\"caption-attachment-62540\" class=\"wp-caption-text\">Test successful (build\/reports\/screenshotTest\/preview\/index.html)<\/p><\/div>\n<p>Since we haven&#8217;t made any changes to our Composable yet, the test has passed successfully. Now we will make some changes to the composable under test, which is a button. We will change its border radius to 30 dp, and we will add 20 dp of horizontal padding to it.<\/p>\n<pre>@Composable\r\nfun PrimaryButton( title:String){\r\n  Button(\r\n    modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp),\r\n    onClick = {},\r\n    shape = RoundedCornerShape(30.dp),\r\n       ) {\r\n          Text(title)\r\n         }\r\n  }<\/pre>\n<p>&nbsp;<\/p>\n<p>Running the same command again &#8211;<br \/>\n<code>.\/gradlew validateDebugScreenshotTest<\/code><\/p>\n<div id=\"attachment_62543\" style=\"width: 840px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-62543\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-62543 \" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/06\/3-1024x326.png\" alt=\"Test failed (build\/reports\/screenshotTest\/preview\/index.html)\" width=\"830\" height=\"264\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/06\/3-1024x326.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/3-300x95.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/3-768x244.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/3-1536x488.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/3-624x198.png 624w, \/blog\/wp-ttn-blog\/uploads\/2024\/06\/3.png 1808w\" sizes=\"(max-width: 830px) 100vw, 830px\" \/><p id=\"caption-attachment-62543\" class=\"wp-caption-text\">Test failed (build\/reports\/screenshotTest\/preview\/index.html)<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>we can see the test failed because the Composable preview does not match the previous screenshot taken. This failure indicates something visual has changed in our composable. We can visualize the report to find out what exactly made the test to fail and handle it accordingly and avoid any UI regression.<\/p>\n<h2>Note<\/h2>\n<p>We have used the two commands above: <code>updateDebugScreenshotTest<\/code> and <code>validateDebugScreenshotTest<\/code>. When it comes to automating these two tasks, <code>validateDebugScreenshot<\/code> Tests can be automated to run with the CI server on each pull request or build (aborting it if the test fails).<br \/>\nAutomating <code>updateDebugScreenshotTest<\/code> can cause issues. If we update reference images each time, then we&#8217;ll lose the old reference, and the test might not run against the right screenshot.<\/p>\n<p>We should run <code>updateDebugScreenshotTest<\/code> only in the following cases:<\/p>\n<p>1. When making changes to a component in a design system.<br \/>\n2. When adding or removing components from an existing screen.<br \/>\n3. When creating a new component or screen, which we will test later.<\/p>\n<h2>Conclusion<\/h2>\n<p>That&#8217;s it. Creating and running screenshot tests for Composable involve just these steps. With these tests, we can improve the UI testing process by detecting visual regressions quickly and with very little effort.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is Screenshot testing Screenshot or snapshot testing is a way to automate the validation of the UI components and widgets. It prevents regressions when updating any existing screen or component. A screenshot testing tool helps render a piece of UI (a screen or component), takes a snapshot of it, and then compares it with [&hellip;]<\/p>\n","protected":false},"author":1271,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":210},"categories":[518],"tags":[4845,6011,6047,6048],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/62366"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1271"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=62366"}],"version-history":[{"count":28,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/62366\/revisions"}],"predecessor-version":[{"id":62670,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/62366\/revisions\/62670"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=62366"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=62366"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=62366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}