Hello Android developers!
We are excited to announce an update for the foldable Test Kit library. Test Kit provides utility methods and classes that help you write instrumented tests for large screen and foldable devices. This update adds annotations which are useful for creating tests for one posture at a time. Now, instead of adding extra code to span an app or simulate a folding feature, you can just add an annotation to set up your tests.
Annotations can be used to configure tests for:
- single-screen or dual-screen modes
- specific target devices
- specific device orientations
- simulated folding features
The annotation syntax is perfect for simple tests where the device remains in the same state for the entire test. The annotations help keep the test code readable and expressive while enabling you to target specific postures and foldable device states.
Test Kit annotations work on any foldable device that supports Jetpack Window Manager, including Surface Duo.
Figure 1: Android Studio screenshot showing simple tests that detect the correct text label is showing based on the device orientation set via an annotation
If you need to test complex app flows including changing the device state during the test, you should simulate a folding feature or use swipe gestures in code, which is also covered in our Test Kit documentation.
How to add Test Kit to your project
The Test Kit components are available on Maven Central. To write tests with the annotations feature, include the dependencies that match your layout preferences (Views or Jetpack Compose) to your app’s build.gradle file:
Views
androidTestImplementation "com.microsoft.device.dualscreen.testing:testing-kotlin:1.0.0-alpha4" androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0" androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0" androidTestImplementation "androidx.test:runner:1.4.0" androidTestImplementation "androidx.test:rules:1.4.0"
Jetpack Compose
androidTestImplementation "com.microsoft.device.dualscreen.testing:testing-compose:1.0.0-alpha04" androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0" androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.1.1"
How it works
The core for these annotations is two utility classes: FoldableTestRule
and FoldableJunit4ClassRunner
.
FoldableTestRule
is a custom TestRule that must be used together with Test Kit annotations (@SingleScreenTest
, @DualScreenTest
, @MockFoldingFeature
and @DeviceOrientation
). Without this rule, the annotations have no effect.
FoldableJUnit4ClassRunner
is a custom AndroidJunit4ClassRunner that validates the parameters for Test Kit annotations, and it is recommended to always use it to make the tests run as intended.
Usage scenarios
This section shows which annotations can be used for different test cases.
Test in single- or dual-screen mode
If you want to run tests in single-screen or dual-screen mode, you should use the @SingleScreenTest
or @DualScreenTest
annotation together with FoldableTestRule and FoldableJUnit4ClassRunner as shown in the following example:
@RunWith(FoldableJUnit4ClassRunner::class) class TestSample { private val activityScenarioRule = activityScenarioRule<MainActivity>() private val foldableTestRule = FoldableTestRule() @get:Rule val testRule: TestRule = foldableRuleChain(activityScenarioRule, foldableTestRule) @Test @DualScreenTest fun sampleTestMethod() { } }
You can use these annotations either at the test class level or test method level, but not both at the same time. You can find more about these annotations here: @SingleScreenTest/@DualScreenTest
Test on a specific device
If you want to run tests on specific target devices, you must use @TargetDevices
annotation with the desired devices provided by the devices
parameter. You can also skip some devices with this annotation using the ignoreDevices
parameter, like in the following example:
@RunWith(FoldableJUnit4ClassRunner::class) @TargetDevices(devices = [DeviceModel.SurfaceDuo]) class TestSample { private val activityScenarioRule = activityScenarioRule<MainActivity>() private val foldableTestRule = FoldableTestRule() @get:Rule val testRule: TestRule = foldableRuleChain(activityScenarioRule, foldableTestRule) @Test fun sampleTestMethod() { // test will ONLY run on Surface Duo devices } }
In this sample, all the methods from TestSample class will run only on Surface Duo devices. You can use this annotation also at the test method level, but not in both places at the same time.
If you want to ignore some devices, you can use it like this:
@RunWith(FoldableJUnit4ClassRunner::class) @TargetDevices(ignoreDevices = [DeviceModel.SurfaceDuo]) class TestSample { private val activityScenarioRule = activityScenarioRule<MainActivity>() private val foldableTestRule = FoldableTestRule() @get:Rule val testRule: TestRule = foldableRuleChain(activityScenarioRule, foldableTestRule) @Test fun sampleTestMethod() { // test will NOT run on Surface Duo devices } }
You can find more about this annotation here: @TargetDevices
Test a specific orientation
You can run tests in a specific device orientation with the @DeviceOrientation annotation, or if you want also to run it on a single-screen or dual-screen posture, you can use @SingleScreenTest
or @DualScreenTest
with the deviceOrientation
parameter, like this:
@RunWith(FoldableJUnit4ClassRunner::class) @DeviceOrientation(orientation = UiAutomation.ROTATION_FREEZE_180) class TestSample { private val activityScenarioRule = activityScenarioRule<MainActivity>() private val foldableTestRule = FoldableTestRule() @get:Rule val testRule: TestRule = foldableRuleChain(activityScenarioRule, foldableTestRule) @Test fun sampleTestMethod() { // test is run at 180 degree rotation } }
@RunWith(FoldableJUnit4ClassRunner::class) @SingleScreenTest(orientation = UiAutomation.ROTATION_FREEZE_180) class TestSample { private val activityScenarioRule = activityScenarioRule<MainActivity>() private val foldableTestRule = FoldableTestRule() @get:Rule val testRule: TestRule = foldableRuleChain(activityScenarioRule, foldableTestRule) @Test fun sampleTestMethod() { // test is run at 180 degree rotation } }
Test with a simulated folding feature
If you want to run tests with a simulated folding feature, you should use @MockFoldingFeature
and provide the windowBounds, center, size, state, or orientation parameter. None of these parameters is required because they have default values, but you can find more info about them here: @MockFoldingFeature
@RunWith(FoldableJUnit4ClassRunner::class) @MockFoldingFeature( size = 2, state = FoldingFeatureState.FLAT, orientation = FoldingFeatureOrientation.HORIZONTAL ) class TestSample { private val activityScenarioRule = activityScenarioRule<MainActivity>() private val foldableTestRule = FoldableTestRule() @get:Rule val testRule: TestRule = foldableRuleChain(activityScenarioRule, foldableTestRule) @Test fun sampleTestMethod() { // test is run with custom folding feature configuration } }
Samples
To make it easier to understand how to use Test Kit annotations, we added a new SDK sample to our Views library. We’ve also updated our Compose samples to use the new annotations in UI tests.
To see examples of how to use each specific annotation, check out the links below:
Annotation name |
Sample code |
---|---|
@SingleScreenTest/@DualScreenTest |
|
@MockFoldingFeature |
|
@TargetDevices |
|
@DeviceOrientation |
Resources and feedback
You can review the documentation for more info. You can also try out our sample and check out all these scenarios.
The source code for the Test Kit is available on GitHub if you’re curious about the implementation or wish to contribute. Also visit the documentation for more information on all the features in the dual-screen library for Kotlin and Java developers. Â
Thanks to the team – Bianca Miron, Cesar Valiente and Kristen Halper for their work on this update.  Â
We’d love to hear from you and how you plan to use the Test Kit library in your apps. Please reach to out using the feedback forum or message us @surfaceduodev on Twitter.  Â
Finally, please join us for our dual screen developer livestream at 11am (Pacific time) each Friday – mark it in your calendar and check out the archives on YouTube.Â
0 comments