Thursday 25 February 2016

Testing Camera Activity using Intent



We have seen how to use intent for inter app testing and so far we have seen how to test Dialer and Browser activity. In the post I will give you simple example for testing Camera Activity. There are many apps which uses camera to capture image and share it. Testing this scenario is now very easy with Espresso Intent.

App Under Testing -
I have created a simple app as per be below screenshot when you click on the camera it launches camera activity then you can capture the image.

Test Camera Activity with Espresso

Test Case Scenario -
1. Launch the app.
2. Take  a photo 
3. check whether the photo is taken and displayed in Image View box.

Test Case Code Description -
1. We need to create a Custom Matcher to check the image view contains image. So create a new Java Class in androidTest folder with name ImageViewMatcher and copy the code given below.
2. In our Test Case class we will stub the camera activity using the app launcher icon image so that we can cross check it. So the method createImageCaptureStub() we put the app drawable image in the bundle and create Intent with the bundle and then pass the same intent as ActivityResult.
3.Before Test case execute we stub the intent so when the app launches camera the drawable image will be passed as part of intend stub.
4. Then In our test case we click on camera button which calls intend and we get the drawable image which we stubbed earlier and we can assert it in our test case.
Custom Matcher -

package com.example.anuja.cameraintentsample;

/**
 * Created by Anuja on 24-02-2016.
 */
import android.support.test.espresso.matcher.BoundedMatcher;
import android.view.View;
import android.widget.ImageView;

import org.hamcrest.Description;
public class ImageViewMatcher {

    public static BoundedMatcher<View, ImageView> hasDrawable() {
        return new BoundedMatcher<View, ImageView>(ImageView.class) {
            @Override
            public void describeTo(Description description) {
                description.appendText("has drawable");
            }

            @Override
            public boolean matchesSafely(ImageView imageView) {
                return imageView.getDrawable() != null;
            }
        };
    }
}

Test Case -


package com.example.anuja.cameraintentsample;

import android.app.Activity;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.app.Instrumentation.ActivityResult;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.intent.Intents.intending;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static android.support.test.espresso.matcher.ViewMatchers.withId;

import static com.example.anuja.cameraintentsample.ImageViewMatcher.hasDrawable;
import static org.hamcrest.Matchers.not;

/**
 * Created by Anuja on 24-02-2016.
 */
@RunWith(AndroidJUnit4.class)
@LargeTest
public class CameraIntentTest {

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

        @Before
        public void stubCameraIntent() {
            ActivityResult result = createImageCaptureStub();

            // Stub the Intent.
            intending(hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result);
        }

        @Test
        public void testTakePhoto() {
            // Check that the ImageView doesn't have a drawable applied.
            onView(withId(R.id.imageView)).check(matches(not(hasDrawable())));

            // Click on the button that will trigger the stubbed intent.
            onView(withId(R.id.button_take_photo)).perform(click());

            // With no user interaction, the ImageView will have a drawable.
            onView(withId(R.id.imageView)).check(matches(hasDrawable()));
        }

        private ActivityResult createImageCaptureStub() {
            // Put the drawable in a bundle.
            Bundle bundle = new Bundle();
            bundle.putParcelable(ImageViewerActivity.KEY_IMAGE_DATA, BitmapFactory.decodeResource(
                    mIntentsRule.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);
        }
    }

I hope this post helps you find your code coverage for your test suit :)
Please Share your feedback in comments section below and follow QA Automated to get latest post update.Happy Testing :-)

6 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. hello, i got this error ```No views in hierarchy found matching: with id: 154541016 (resource name not found)```
    after open.

    ReplyDelete
  3. How to do the same thing for selecting a image from File manager?

    ReplyDelete
  4. Getting the following error:

    W/ActivityTestRule: getActivityIntent() returned null using default: Intent(Intent.ACTION_MAIN)

    ReplyDelete