What’s new in Android Testing

During Droidcon Italy Stephan Linzner from Google explained upcoming features in the Android Testing Support Library. Lets have a closer look at some:


Test Filtering

If you want to suppress a test to run on certain target Api levels, just add the @SdkSuppress annotation.

@SdkSuppress(minSdkVersion=15)
@Test
public void featureWithMinSdk15() {
  ...
}

You can also filter tests to only run on a (physical) device by adding the @RequiresDevice annotation.

@RequiresDevice
@Test
public void SomeDeviceSpecificFeature() {
  ...
}


ActivityTestRule

Because ActivityInstrumentationTestCase2 will become deprecated you need to define a @Rule.

Rules allow very flexible addition or redefinition of the behavior of each test method in a test class

https://github.com/junit-team/junit/wiki/Rules



So in your test add a @Rule annotation, and create an ActivityTestRule for your Activity

@RunWith(AndroidJUnit4.class)
@LargeTest
public class ChangeTextBehaviorTest {
    ...

    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void changeText_sameActivity() {
        // Type text and then press the button.
        onView(withId(R.id.editTextUserInput)).perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard());
        onView(withId(R.id.changeTextBt)).perform(click());

        // Check that the text was changed.
        onView(withId(R.id.textToBeChanged)).check(matches(withText(STRING_TO_BE_TYPED)));
    }
}

Now create your ActivityTestRule

public class ActivityTestRule<T extends Activity> {

    public T getActivity() {}

    protected Intent getActivityIntent() {}

    protected void beforeActivityLaunched() {}

    protected void afterActivityFinished() {}
}


Espresso-Intents

Espresso-Intents is like Mockito but for Intent, basically hermetic inter-app testing.
To give you an example, lets say in your application when a user presses a “call” button, you want to know if the correct data will be send to the Intent.ACTION_CALL.

EspressoIntent

So first create an IntentsTestRule and then verify that the Intent was sent using Espresso-Intents

@RunWith(AndroidJUnit4.class)
@LargeTest
public class DialerActivityTest {
    ...
    @Rule
    public IntentsTestRule<DialerActivity> mRule = new IntentsTestRule<>(DialerActivity.class);

    @Test
    public void typeNumber_ValidInput_InitiatesCall() {
        onView(withId(R.id.edit_text_caller_number)).perform(typeText(VALID_PHONE_NUMBER),
                closeSoftKeyboard());
        onView(withId(R.id.button_call_number)).perform(click());

        intended(allOf(
                hasAction(is(equalTo(Intent.ACTION_CALL))),
                hasData(equalTo(INTENT_DATA_PHONE_NUMBER)),
                toPackage(PACKAGE_ANDROID_DIALER)));
    }
}



So now you know…


All code can be found in android-testing github:



Thanks Stephan Linzner for the resources. #HappyTesting