When you have screens within your Android app that have camera and/or gallery features with some screen changes (views, labels or buttons that appear/disappear, etc) and you need to write some Espresso tests for those features/screens there are a couple of helpers that Ive been using and I want to share with you all.Granting PermissionsWhen you are using the Camera within your app, you need to grant some permissions in the device in order to read/store a photo. These permissions are asked in runtime an usually are related to READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE.
Thus, the GrantPermissionRule allows granting of runtime permissions on Android M (API 23) and above and when applied to a test class this Rule attempts to grant all requested runtime permissions.@get:Rulevar mRuntimePermissionRule = GrantPermissionRule.grant(android.
Manifest.permission.WRITE_EXTERNAL_STORAGE)This Rule is usually used to grant runtime permissions to avoid the permission dialog from showing up and blocking the Apps Ui, and according to official documentation:As per this rule will automatically grant READ_EXTERNAL_STORAGE when WRITE_EXTERNAL_STORAGE is requestedGallery TestThe code to test when a gallery icon is clicked in the app, then an image is picked and shown in the screen:The first thing here is that I have a helper method (CameraAndGallery.
savePickedImage) that first saves an image (for brevity the ic_launcher icon) that is going to be used in the test as a local file visible for the test:The activity parameter comes from the ActivityTestRule:@get:Rulevar mActivityTestRule = IntentsTestRule(MyActivity::class.java)Then I create an ActivityResult object (like a mock but for Android Intent) that is going to be used by the Espresso Intents matcher (to match and validate the outgoing intents):val imgGalleryResult = CameraAndGallery.createImageGallerySetResultStub(mActivityTestRule.
activity) intending(hasAction(Intent.ACTION_CHOOSER)).respondWith(imgGalleryResult)The secret here is to ask for the file previously saved and finally used as the result.
Note: To work with espresso intents, we must to add this dependency to apps build. gradle file:androidTestImplementation androidx.test.
espresso:espresso-intents:$espressoVersionFor the test we are writing, lets asume that the image picked from the Gallery, we are setting it in an ImageView that is visible for the user, then the final part of the test is to check that the image is displayed (method hasImageSet()):onView(withId(R.id.auctionphotos_bigimage_viewer)).
check(matches(hasImageSet()))Camera TestSimilar to Gallery Test, the test to get an image from the device Camera follows the almost the same steps, but in this case an image doesnt need to be saved before, only mock the result of the camera:The mocked capture result as follows:The resulting image is going to be taken by the intent:intending(hasAction(MediaStore. ACTION_IMAGE_CAPTURE)). respondWith(imgCaptureResult)And with that we can check if the image was taken and displayed:onView(withId(R.
id.auctionphotos_bigimage_viewer)).check(matches(hasImageSet()))Finally, if you want to explore a little bit more content regarding Espresso tests and Intents, you may want to take a look of this repo from official Android team
Shenzhen TigerWong Technology Co.,Ltd
Tel: +86 13717037584
E-Mail: info@sztigerwong.com
Add: 1st Floor, Building A2, Silicon Valley Power Digital Industrial Park, No. 22 Dafu Road, Guanlan Street, Longhua District,
Shenzhen,GuangDong Province,China