How to Testing your intent with Espresso


Android system uses intent for communication. Intent can contain information (component, action, category, data, extras and more). We can send the intent to other application and can get it from other application too.

In this blog we will create the simple application can take a photo and show photo in the image view.

screenshot-2016-07-16-23-19-34

When click on “Take a Photo” button, it will send intent to launch camera application. Then when photo was taken, the bitmap photo result will return back to onActivityResult method.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            if (extras == null || !extras.containsKey("data")) {
                return;
            }
            Bitmap imageBitmap = (Bitmap) extras.get("data");
            mImageView.setImageBitmap(imageBitmap);
        }
    }

Setup

    defaultConfig {
        ...
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    dependencies {
        ...
        androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
        androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
    }

Write the Test

Create activity test class and add runner annotation.

    @RunWith(AndroidJUnit4.class)
    public class TakePhotoActivityTest {

    }

Add intent test rule.

    @Rule
    public IntentsTestRule mIntentsRule = new IntentsTestRule<>(TakePhotoActivityTest.class);

First test, when click on “Take a Photo” button, it will open camera application.

    @Test
    public void takePhoto_shouldOpenCamera() {
        onView(withId(R.id.btn_take_photo)).perform(click());

        intended(hasAction(equalTo(MediaStore.ACTION_IMAGE_CAPTURE)));
    }

Camera app launched by receiving intent that contain ACTION_IMAGE_CAPTURE, so we will test the camera app receive ACTION_IMAGE_CAPTURE or not by using intended.

The Second test, that image view will show the image, when taken a photo.

Stub the bitmap image result.

    private ActivityResult createImageCaptureActivityResultStub() {
        // Put the drawable in a bundle.
        Bundle bundle = new Bundle();
        bundle.putParcelable("data", BitmapFactory.decodeResource(
                activityTestRule.getActivity().getResources(), R.drawable.ic_launcher));

        // Create the Intent that will include the bundle.
        Intent resultData = new Intent();
        resultData.putExtras(bundle);

        // Create the ActivityResult with the Intent.
        return new ActivityResult(Activity.RESULT_OK, resultData);
    }

Create custom matcher hasDrawable.

    public class ImageViewHasDrawableMatcher {

        public static BoundedMatcher<View, ImageView> hasDrawable() {
            return new BoundedMatcher<View, ImageView>(ImageView.class) {
                @Override
                protected boolean matchesSafely(ImageView imageView) {
                    return imageView.getDrawable() != null;
                }

                @Override
                public void describeTo(Description description) {
                    description.appendText("has drawable");
                }
            };
        }

    }

Then, use it to check that image view has drawable or not.

    @Test
    public void takePhoto_imageViewHasDrawable() {
        // check the image view should not has drawable at the first time.
        onView(withId(R.id.image_view)).check(matches(not(hasDrawable())));
        // click on "Take a Photo" button, it will trigger the stubbed intend.
        onView(withId(R.id.btn_take_photo)).perform(click());
        // now the image view should has drawable.
        onView(withId(R.id.image_view)).check(matches(hasDrawable()));
    }

Run test!
Screenshot 2016-07-16 23.27.16

For more information: Android Testing Support Library


Leave a Reply

Your email address will not be published.