{"id":2342,"date":"2022-03-24T11:40:29","date_gmt":"2022-03-24T18:40:29","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=2342"},"modified":"2022-03-24T11:40:29","modified_gmt":"2022-03-24T18:40:29","slug":"foldable-ui-test-kit","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/foldable-ui-test-kit\/","title":{"rendered":"Write foldable tests quickly with Test Kit"},"content":{"rendered":"<p>\n  Hello Android developers!\n<\/p>\n<p>\n  This week, we\u2019re super excited to announce that we\u2019ve released the first version of our foldable Test Kit. The Test Kit currently includes two testing utility libraries, one for layouts built with views and another for layouts built with Jetpack Compose, and we\u2019re looking forward to adding more testing capabilities in the future!\n<\/p>\n<h2>Library overview<\/h2>\n<p>\n  The goal of these testing libraries is to make it easier to write UI tests for foldables. We\u2019ve included several different helper methods for creating mock folding features, simulating spanning gestures, and other useful utilities. To learn more about the Test Kit, refer to the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/test-kit\/?tabs=views\">documentation<\/a>.\n<\/p>\n<p>\n  One important note is that the Compose library is based on the view system library, so you only need to import <strong>one version<\/strong> in any project. If you\u2019re only using views, then you should import the view system library:<\/p>\n<pre>com.microsoft.dualscreen.testing:testing-kotlin<\/pre>\n<p>Otherwise, you should import the Compose library:<\/p>\n<pre>com.microsoft.dualscreen.testing:testing-compose<\/pre>\n<h3>View system library<\/h3>\n<p>\n  The <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/tree\/main\/utils\/test-utils\">view system library<\/a> is the basis of the Test Kit and was originally created because we found ourselves using the same helper functions over and over again in our UI tests. When you import the library, you\u2019ll have access to the following utilities:\n<\/p>\n<ol>\n<li><strong><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/CurrentActivityDelegate.kt\">CurrentActivityDelegate<\/a><\/strong>\n<p>\n  Set up and support a test scenario from an <code>ActivityTestRule<\/code> and helps you to ensure that the Activity is running before to use any view or assertion, and any configuration change.\n<\/p>\n<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/DeviceModel.kt\"><strong>DeviceModel<\/strong><\/a><strong> &amp; <\/strong><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/UiDeviceExtensions.kt\"><strong>UiDeviceExtensions<\/strong><\/a>\n<p>\n  Simulate dual-screen swipe gestures on both Surface Duo models and change device orientation.\n<\/p>\n<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/FoldingFeatureHelper.kt\"><strong>FoldingFeatureHelper<\/strong><\/a>\n<p>\n  Simulate folding features with different properties, including those of other foldable devices, with the <a href=\"https:\/\/developer.android.com\/reference\/androidx\/window\/testing\/layout\/package-summary\">Jetpack Window Manager testing artifact<\/a>.\n<\/p>\n<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/ForceClick.kt\"><strong>ForceClick<\/strong><\/a>\n<p>\n  Simulate a force click with a <code>ViewAction<\/code> extension used specifically after configuration changes.\n<\/p>\n<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/ViewMatcher.kt\"><strong>ViewMatcher<\/strong><\/a>\n<p>\n  Check if a view is shown in the display area given its position and screen dimensions.\n<\/p>\n<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/blob\/main\/utils\/test-utils\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/WindowLayoutInfoConsumer.kt\"><strong>WindowLayoutInfoConsumer<\/strong><\/a><strong>.<\/strong>\n<p>\n  Monitor and reset <code>WindowLayoutInfo<\/code> data in a test activity.\n<\/p>\n<\/li>\n<\/ol>\n<h3>Compose library<\/h3>\n<p>\n  The <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-sdk\/tree\/main\/ComposeTesting\">Compose library<\/a> builds on the view system library by adding helper functions that are useful for Compose UI tests. When you import this library, you\u2019ll have access to all of the functionality described above, in addition to the following Compose utilities:\n<\/p>\n<ol>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-sdk\/blob\/main\/ComposeTesting\/library\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/compose\/FoldingFeatureHelper.kt\"><strong>FoldingFeatureHelper<\/strong><\/a>\n<p>\n  Provides Compose wrappers for the <code>FoldingFeatureHelper<\/code> methods from the view system library.\n<\/p>\n<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-sdk\/blob\/main\/ComposeTesting\/library\/src\/main\/java\/com\/microsoft\/device\/dualscreen\/testing\/compose\/StringHelper.kt\"><strong>StringHelper<\/strong><\/a>\n<p>\n  Access string resources during UI tests with an <code>AndroidComposeTestRule<\/code>.\n<\/p>\n<\/li>\n<\/ol>\n<h2>Write foldable tests with less code<\/h2>\n<p>\n  If you\u2019ve been following our blog in the past, you may have seen our posts about foldable testing tips with <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/surface-duo-testing-tips-tricks\/#espresso-user-interface-testing\">Espresso<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/jetpack-compose-ui-test\/#test-layouts-on-large-screens-and-foldables\">Jetpack Compose<\/a>. \n<\/p>\n<pre>@Test \r\nfun\u202fisAppSpanned()\u202f{\r\n \u202f\u202f\u202fval\u202fdevice\u202f=\u202fUiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) \r\n\r\n\u202f\u202f\u202f\u202f\/\/ span the app (from the left side) \r\n\u202f\u202f\u202f\u202fdevice.swipe(675,\u202f1780,\u202f1350,\u202f900, 400)\u202f\u202f\u202f\u202f\u202f\u202f\u202f\u202f\r\n\r\n \u202f\u202f\u202f\/\/ test a UI element \r\n\u202f\u202f\u202f\u202fonView(withText(\"your-text-to-test\")).check(matches(isDisplayed())) \r\n}<\/pre>\n<p><em>Code snippet from Surface Duo testing tips &amp; tricks blog post for spanning during an Espresso test<\/em>\n<\/p>\n<p>\n  You may have also tried out foldable testing in the<a href=\"https:\/\/developer.android.com\/codelabs\/android-window-manager-dual-screen-foldables#8\"> Jetpack Window Manager codelab<\/a>. \n<\/p>\n<pre>@Test\r\nfun testText_is_left_of_Vertical_FoldingFeature() {\r\n\u00a0 \u00a0activityRule.scenario.onActivity { activity -&gt;\r\n\u00a0 \u00a0 \u00a0 \u00a0val hinge = FoldingFeature(\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0activity = activity,\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0state = FLAT,\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0orientation = VERTICAL,\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0size = 2\r\n\u00a0 \u00a0 \u00a0 \u00a0)\r\n\u00a0 \u00a0 \u00a0 \u00a0val expected = TestWindowLayoutInfo(listOf(hinge))\r\n\u00a0 \u00a0 \u00a0 \u00a0publisherRule.overrideWindowLayoutInfo(expected)\r\n\u00a0 \u00a0}\r\n\r\n\u00a0 \u00a0\/\/ Add Assertion with EspressoMatcher here\r\n}<\/pre>\n<p><em>Code snippet from JWM codelab for simulating a folding feature<\/em>\n<\/p>\n<p>\n  Either way, you can see how these code snippets could be hard to understand from a beginner\u2019s point-of-view and could lead to mistakes due to incorrect swipe coordinates or folding feature properties. With the Test Kit, our goal was to make tests more readable and easier to write. In the modified code snippets below, you can see how the same tests would look when using our libraries:\n<\/p>\n<pre>@Test \r\nfun\u202fisAppSpanned()\u202f{\r\n \u202f\u202f\u202fval\u202fdevice\u202f=\u202fUiDevice.getInstance(InstrumentationRegistry.getInstrumentation())\r\n  \t\r\n\u202f\u202f\u202f\u202f\/\/ span the app (from the left side) \r\n    device.spanFromStart()\r\n\r\n\u202f\u202f\u202f\u202f\/\/ test a UI element \r\n\u202f\u202f\u202f\u202fonView(withText(\"your-text-to-test\")).check(matches(isDisplayed())) \r\n}<\/pre>\n<p><em>Updated code snippet based on Surface Duo testing tips &amp; tricks blog post that uses the Test Kit to span during an Espresso test<\/em>\n<\/p>\n<pre>@Test\r\nfun testText_is_left_of_Vertical_FoldingFeature() {\r\n   publisherRule.simulateVerticalFoldingFeature(activityRule, size = 2, state = FLAT)\r\n\r\n\u00a0 \u00a0\/\/ Add Assertion with EspressoMatcher here\r\n}<\/pre>\n<p><em>Updated code snippet based on JWM codelab that uses the Test Kit to simulate a folding feature<\/em>\n<\/p>\n<p>\n  You can see how you no longer need to calculate the exact coordinates for a swipe; in the library, we dynamically determine the coordinates by checking the size and orientation of a device. And for simulating folding features, it\u2019s a lot easier to focus on passing in the relevant properties now that the boilerplate code is part of the helper method implementation.\n<\/p>\n<h2>Add to your project<\/h2>\n<p>\n  When writing your own foldable tests, we hope you also find that the Test Kit makes the whole process easier!\n<\/p>\n<p>\n  To import the Test Kit, follow these steps:\n<\/p>\n<ol>\n<li>\n  Make sure you have the <code>mavenCentral()<\/code> repository in your top-level <strong>build.gradle<\/strong> file:<\/p>\n<pre>allprojects {\r\n    repositories {\r\n        google()\r\n        mavenCentral()\r\n     }\r\n}<\/pre>\n<\/li>\n<li>\n  Ensure the <code>compileSdkVersion<\/code> and <code>targetSdkVersion<\/code> are set to API 31 or newer in your module-level <strong>build.gradle<\/strong> file:<\/p>\n<pre>android { \r\n    compileSdkVersion 31\r\n    defaultConfig { \r\n        targetSdkVersion 31 \r\n    } \r\n    ...\r\n}<\/pre>\n<\/li>\n<li>\n  Add one of the following dependencies to your module-level <strong>build.gradle<\/strong> file:<\/p>\n<p><strong>View system library<\/strong>\n<\/p>\n<pre>implementation \"com.microsoft.dualscreen.testing:testing-kotlin:1.0.0-alpha2\"<\/pre>\n<p><strong>Compose library<\/strong><\/p>\n<pre>  implementation \"com.microsoft.dualscreen.testing:testing-compose:1.0.0-alpha03\"<\/pre>\n<\/li>\n<\/ol>\n<p>\n  Once you\u2019ve imported the correct library version, you can start setting up your test classes and writing tests. To test UI behavior on foldables, you have two options: <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/test-kit\/swipe-gesture?tabs=views\">swipe gestures<\/a> or <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/test-kit\/folding-feature?tabs=views\">mock folding features<\/a>.\n<\/p>\n<p>\n  The first option works best on dual-screen devices like Surface Duo, where certain gestures are needed to change app display state. Our helper methods use the <code>swipe<\/code> method from the <a href=\"https:\/\/developer.android.com\/training\/testing\/other-components\/ui-automator\">UiAutomator<\/a> testing framework to simulate gestures like spanning, unspanning, switching, and closing apps. The animation below shows a <a href=\"https:\/\/github.com\/microsoft\/surface-duo-dual-screen-experience-example\/blob\/main\/app\/src\/androidTest\/java\/com\/microsoft\/device\/samples\/dualscreenexperience\/presentation\/product\/ProductNavigationDualScreenTest.kt#L57\">UI test from our dual-screen experience example<\/a> that performs a spanning swipe:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"800\" height=\"572\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/animation-of-the-openproductsinduallandscapemode.gif\" class=\"wp-image-2343\" alt=\"Animation of the &quot;openProductsInDualLandscapeMode&quot; test running on the Surface Duo emulator, where the dual-screen experience example is spanned and then the device is rotated before running the test\" \/>\n<\/p>\n<p><em>Figure 1. Animation of the <code>openProductsInDualLandscapeMode<\/code> test<\/em>\n<\/p>\n<p>\n  The second option works on all kinds of foldables, so we would recommend using this approach to make sure your apps work well on many devices. Our helper methods use the <a href=\"https:\/\/developer.android.com\/reference\/androidx\/window\/testing\/layout\/package-summary\">Jetpack Window Manager testing artifact<\/a> to send mock folding features to a test rule\u2019s activity. The animation below shows a <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/blob\/main\/NavigationRail\/src\/androidTest\/java\/com\/microsoft\/device\/display\/samples\/navigationrail\/PaneSynchronizationTest.kt#L60\">UI test from our Compose NavigationRail sample<\/a> that simulates a vertical folding feature:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"800\" height=\"572\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/animation-of-the-app_verticalfold_testplaceholder.gif\" class=\"wp-image-2344\" alt=\"Animation of the &quot;app_verticalFold_testPlaceholderViewAppearsOnStart&quot; test running on the Surface Duo emulator, where the Compose NavRail sample opens in the left pane and then a vertical folding feature is simulated before running the UI test\" \/>\n<\/p>\n<p><em>Figure 2. Animation of the <code>app_verticalFold_testPlaceholderViewAppearsOnStart<\/code> test<\/em>\n<\/p>\n<h2>Samples<\/h2>\n<p>\n  To see more examples of how to use the Test Kit, check out these resources:\n<\/p>\n<table>\n<tr>\n<td>\n<p><strong>Test Kit Utility<\/strong>\n<\/p>\n<\/td>\n<td>\n<p><strong>Samples that demonstrate this feature<\/strong>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  CurrentActivityDelegate\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\">Surface Duo SDK<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  DeviceModel &amp; UiDeviceExtensions\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\">Surface Duo SDK<\/a>\n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-dual-screen-experience-example\">Dual-screen experience example<\/a>\n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-sdk\/tree\/main\/ComposeTesting\/sample\/src\/androidTest\/java\/com\/microsoft\/device\/dualscreen\/testing\/sample\">ComposeTesting sample<\/a>\n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/FoldingVideoPlusChat\">FoldingVideo<\/a>\n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/PhotoEditor\">PhotoEditor<\/a>\n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/SourceEditor\">Source Editor<\/a>\n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/TwoNote\">TwoNote<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  FoldingFeatureHelper\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/\">Surface Duo Compose samples<\/a> \n<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-sdk\/tree\/main\/ComposeTesting\/sample\/src\/androidTest\/java\/com\/microsoft\/device\/dualscreen\/testing\/sample\">ComposeTesting sample<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  ForceClick\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\">Surface Duo SDK<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  ViewMatcher\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\">Surface Duo SDK<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  WindowLayoutInfoConsumer\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\">Surface Duo SDK<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\n  StringHelper\n<\/p>\n<\/td>\n<td>\n<p><a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/\">Surface Duo Compose samples<\/a>\n<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<h2>Resources and feedback<\/h2>\n<p>\n  Check out the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/\" target=\"_blank\" rel=\"noopener\">Surface Duo developer documentation<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/\" target=\"_blank\" rel=\"noopener\">past blog posts<\/a> for links and details on all our samples. You can find our <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples-kotlin\">samples on GitHub<\/a>.\u00a0\n<\/p>\n<p>\n  If you have any questions about the Test Kit, or would like to tell us about your apps, use the <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\" target=\"_blank\" rel=\"noopener\">feedback forum<\/a> or message us on Twitter <a href=\"https:\/\/twitter.com\/surfaceduodev\" target=\"_blank\" rel=\"noopener\">@surfaceduodev<\/a>.\u00a0\n<\/p>\n<p>\n  Finally, please join us on <a href=\"https:\/\/twitch.tv\/surfaceduodev\">Twitch<\/a> on Friday 25th March at 11am Pacific time to discuss foldable app testing. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Android developers! This week, we\u2019re super excited to announce that we\u2019ve released the first version of our foldable Test Kit. The Test Kit currently includes two testing utility libraries, one for layouts built with views and another for layouts built with Jetpack Compose, and we\u2019re looking forward to adding more testing capabilities in the [&hellip;]<\/p>\n","protected":false},"author":72597,"featured_media":2353,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[692,473,46,571],"class_list":["post-2342","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-jetpack-compose","tag-kotlin","tag-surface-duo","tag-testing"],"acf":[],"blog_post_summary":"<p>Hello Android developers! This week, we\u2019re super excited to announce that we\u2019ve released the first version of our foldable Test Kit. The Test Kit currently includes two testing utility libraries, one for layouts built with views and another for layouts built with Jetpack Compose, and we\u2019re looking forward to adding more testing capabilities in the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/72597"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=2342"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2342\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/2353"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=2342"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=2342"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=2342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}