How to click on the Android gallery with espresso

We currently have an Android app that we are testing with Espresso. One of the features we want to test is the selection of the image / image from the local image gallery. We can get all the way to the gallery view, but then we cannot choose from Recent, Downloads, Gallery in the window that appears. A fragment of how we got to how we did this is given below.

public void testShouldBeAbleToSelectPhotoFromGallery() { getActivity(); // given onView(withId(launch_gallery_button)).perform(click()); onView(withText("Gallery")).perform(click()); // this is a button in our app // then we get stuck :( } 

Thanks!

+7
source share
3 answers

This is not possible with Robotium or Espresso, since they only work with the actions of the application under test.

You can use the UiAutomator framework provided by Google to write integration tests that work across different Android apps and embedded apps.

Basically, you analyzed the gallery app in uiautomatorview to find out how to select the ui elements needed for your test case and then act on them, unlike Espresso.

+4
source

If you want to test this functionality in your application, you must use the intention of mocking functionality in Espresso. Espresso tests should not leave your application in the first place. Instead, you will catch the intention that you use to open the gallery application and return the result back to your application. During the test, you will remain in your application, you will immediately get the result.

To do this, check the intending and intended api of espresso.

Here is a Pengj lesson to introduce you to deliberate ridicule. The tutorial mentions Mockito, but you can use it without it.

+2
source

The best and right way is to use Espresso Intents. So you need to add a dependency to your build.gradle application

 androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" 

In my case, I opened the gallery using a button in my application, then the code for the test and adding the target and intended Espresso APIs as follows:

 @Test fun photos_CreationGalleryClickUI() { savePickedImage() val imgGalleryResult = createImageGallerySetResultStub() intending(hasAction(Intent.ACTION_CHOOSER)).respondWith(imgGalleryResult) onView(withId(R.id.photos_button_gallery)).perform(click()) onView(withId(R.id.photos_bigimage_viewer)).check(matches(hasImageSet())) } 

Here, matching for indexing is the key when the gallery should be open and avoid manually selecting an image:

 hasAction(Intent.ACTION_CHOOSER) 

I use two helpers: savePickedImage () to simulate an image from the gallery

 private fun savePickedImage() { val bm = BitmapFactory.decodeResource(mActivityTestRule.activity.resources, R.mipmap.ic_launcher) assertTrue(bm != null) val dir = mActivityTestRule.activity.externalCacheDir val file = File(dir?.path, "myImageResult.jpeg") System.out.println(file.absolutePath) val outStream: FileOutputStream? try { outStream = FileOutputStream(file) bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream) outStream.flush() outStream.close() } catch (e: FileNotFoundException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } } 

And createImageGallerySetResultStub to stub the result after the "select" image. Here it would be important to put the result in the form of an array of packages, without it the result would never be recognized:

 private fun createImageGallerySetResultStub(): Instrumentation.ActivityResult { val bundle = Bundle() val parcels = ArrayList<Parcelable>() val resultData = Intent() val dir = mActivityTestRule.activity.externalCacheDir val file = File(dir?.path, "myImageResult.jpeg") val uri = Uri.fromFile(file) val myParcelable = uri as Parcelable parcels.add(myParcelable) bundle.putParcelableArrayList(Intent.EXTRA_STREAM, parcels) resultData.putExtras(bundle) return Instrumentation.ActivityResult(Activity.RESULT_OK, resultData) } 

hasImageSet () as a match helper that checks if imageView has or not:

 return item.getDrawable() == null 

NOTE. Remember to set the grant rule to avoid permission problems and define the test rule as an IntentTestRule (which is already expanding from ActivityTestRule)

 @get:Rule var mActivityTestRule = IntentsTestRule(AuctionCreationActivity::class.java) 

@get: Rule var mRuntimePermissionRule = GrantPermissionRule.grant (android.Manifest.permission.WRITE_EXTERNAL_STORAGE)

Dependence:

 androidTestImplementation "androidx.test:rules:$testRules" 
0
source

Source: https://habr.com/ru/post/976984/


All Articles