How to click on Android Gallery with Espresso

岁酱吖の 提交于 2020-01-02 02:35:09

问题


We currently have an Android application that we are testing with Espresso. One of the features we want to test is selecting a picture/image from the local image gallery. We can get all the way to bringing up the Gallery view, but then cannot select from Recent, Downloads, Gallery in the resulting window. A snippet as to how we got as far as we did is included 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!


回答1:


This is not possible with with either Robotium or Espresso, as they only work on Activities of the app under test.

To write integration tests that work across different apps and Android built-in apps, you can use the UiAutomator framework provided by Google.

Basically you would analyse the gallery app in the uiautomatorview to learn how to select the ui elements your test case needs and then act on them, not unlike Espresso.




回答2:


If you want to test that functionality in your app you should use the intent mocking functionality in Espresso. Espresso tests should not leave your app in the first place. Instead you catch the intent you use to open the gallery app and return a result back to your app. During the test you will stay in your app, you will get a result immediately.

To do this check the intending and intended api's of Espresso.

Here is a tutorial by Pengj to get you acquainted with intent mocking. The tutorial mentions Mockito but you can perfectly use this without it.




回答3:


The best and proper way is to use Espresso Intents. So you need to add the dependency in your app's build.gradle

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

In my case I was openning the gallery from a button within my app, then the code for the test and the addition of the intending and intended api's of Espresso 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 the matcher for intending is the key when the gallery needs to be open and avoid to manually pick an image:

hasAction(Intent.ACTION_CHOOSER)

I' using two helpers: savePickedImage() to mock 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 stubbing the result after "picking" the image. Here putting the result as an array of parcelables was key, without it, the never result was never 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 matcher helper that checks if the imageView has or not a drawable:

return item.getDrawable() == null

NOTE: Remember to set the grant rule to avoid problems with the permissions and to define your test rule as an IntentTestRule (which extends from ActivityTestRule already)

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

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

The dependency:

androidTestImplementation "androidx.test:rules:$testRules"


来源:https://stackoverflow.com/questions/26469661/how-to-click-on-android-gallery-with-espresso

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!