Upgrade to Pro — share decks privately, control downloads, hide ads and more …

State of Android Testing Support Library

State of Android Testing Support Library

GDG DevFest Dublin 07/11/2015

Iñaki Villar

November 07, 2015
Tweet

More Decks by Iñaki Villar

Other Decks in Technology

Transcript

  1. Android Instrumentation Instrumentation AndroidJunitRunner AndroidJunit4 defaultConfig {
 applicationId "com.example.devfest"
 minSdkVersion

    10
 targetSdkVersion 23
 versionCode 1
 versionName "1.0"
 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
 } androidTestCompile 'com.android.support.test:runner:0.4'

  2. Android Instrumentation Instrumentation AndroidJunitRunner AndroidJunit4 defaultConfig {
 applicationId "com.example.devfest"
 minSdkVersion

    10
 targetSdkVersion 23
 versionCode 1
 versionName "1.0"
 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
 } androidTestCompile 'com.android.support.test:runner:0.4'

  3. Rules public class MainActivityTest {
 
 @Rule
 public ActivityTestRule<MainActivity> activityTestRule

    = new ActivityTestRule<>(MainActivity.class);
 
 @Test
 public void findViewPerformActionDone() { }
 
 }
  4. Rules public class MainActivityTest {
 
 @Rule
 public ActivityTestRule<MainActivity> activityTestRule

    = new ActivityTestRule<>(MainActivity.class);
 
 @Test
 public void findViewPerformActionDone() { }
 
 } @Test
 public void testWithBoundService() {
 IBinder binder = serviceRule.bindService(
 new Intent(InstrumentationRegistry.getTargetContext(), MyService.class));
 MyService service = ((MyService.LocalBinder) binder).getService();
 assertTrue("True wasn't returned", service.doSomethingToReturnTrue());
 }
 @Rule
 public final ServiceTestRule serviceRule = new ServiceTestRule();
 
 

  5. Filters @RequiresDevice
 public void findRequiredDeviceToTest(){
 }
 @FlakyTest
 public void findSomeFlakyTest(){


    
 } @SdkSuppress(minSdkVersion = 21)
 public void findSomePropertyDevice(){
 }

  6. ViewMatchers Espresso public static Matcher<View> withId(final int id) {
 return

    new TypeSafeMatcher<View>() {
 Resources resources = null;
 @Override
 public void describeTo(Description description) {
 String idDescription = Integer.toString(id);
 if (resources != null) {
 try {
 idDescription = resources.getResourceName(id);
 } catch (Resources.NotFoundException e) {
 // No big deal, will just use the int value.
 idDescription = String.format("%s (resource name not found)", id);
 }
 }
 description.appendText("with id: " + idDescription);
 }
 
 @Override
 public boolean matchesSafely(View view) {
 resources = view.getResources();
 return id == view.getId();
 }
 };
 }

  7. ViewMatchers Espresso public static Matcher<View> withId(final int id) {
 return

    new TypeSafeMatcher<View>() {
 Resources resources = null;
 @Override
 public void describeTo(Description description) {
 String idDescription = Integer.toString(id);
 if (resources != null) {
 try {
 idDescription = resources.getResourceName(id);
 } catch (Resources.NotFoundException e) {
 // No big deal, will just use the int value.
 idDescription = String.format("%s (resource name not found)", id);
 }
 }
 description.appendText("with id: " + idDescription);
 }
 
 @Override
 public boolean matchesSafely(View view) {
 resources = view.getResources();
 return id == view.getId();
 }
 };
 }

  8. ViewMatchers Espresso public static Matcher<View> withId(final int id) {
 return

    new TypeSafeMatcher<View>() {
 Resources resources = null;
 @Override
 public void describeTo(Description description) {
 String idDescription = Integer.toString(id);
 if (resources != null) {
 try {
 idDescription = resources.getResourceName(id);
 } catch (Resources.NotFoundException e) {
 // No big deal, will just use the int value.
 idDescription = String.format("%s (resource name not found)", id);
 }
 }
 description.appendText("with id: " + idDescription);
 }
 
 @Override
 public boolean matchesSafely(View view) {
 resources = view.getResources();
 return id == view.getId();
 }
 };
 }

  9. Espresso Intents IntentsTestRule<T extends Activity> extends ActivityTestRule<T> @Override
 protected void

    afterActivityLaunched() {
 Intents.init();
 super.afterActivityLaunched();
 }
 
 @Override
 protected void afterActivityFinished() {
 super.afterActivityFinished();
 Intents.release();
 }
  10. Espresso Intents Intended @Test
 public void typeNumber_ValidInput_InitiatesCall() {
 // Types

    a phone number into the dialer edit text field and presses the call button.
 onView(withId(R.id.edit_text_caller_number))
 .perform(typeText(VALID_PHONE_NUMBER), closeSoftKeyboard());
 onView(withId(R.id.button_call_number)).perform(click());
 
 // Verify that an intent to the dialer was sent with the correct action, phone
 // number and package. Think of Intents intended API as the equivalent to Mockito's verify.
 intended(allOf(
 hasAction(Intent.ACTION_CALL),
 hasData(INTENT_DATA_PHONE_NUMBER),
 toPackage(PACKAGE_ANDROID_DIALER)));
 }
  11. Espresso Intents Intended @Test
 public void typeNumber_ValidInput_InitiatesCall() {
 // Types

    a phone number into the dialer edit text field and presses the call button.
 onView(withId(R.id.edit_text_caller_number))
 .perform(typeText(VALID_PHONE_NUMBER), closeSoftKeyboard());
 onView(withId(R.id.button_call_number)).perform(click());
 
 // Verify that an intent to the dialer was sent with the correct action, phone
 // number and package. Think of Intents intended API as the equivalent to Mockito's verify.
 intended(allOf(
 hasAction(Intent.ACTION_CALL),
 hasData(INTENT_DATA_PHONE_NUMBER),
 toPackage(PACKAGE_ANDROID_DIALER)));
 }
  12. Espresso Intents Intended @Test
 public void typeNumber_ValidInput_InitiatesCall() {
 // Types

    a phone number into the dialer edit text field and presses the call button.
 onView(withId(R.id.edit_text_caller_number))
 .perform(typeText(VALID_PHONE_NUMBER), closeSoftKeyboard());
 onView(withId(R.id.button_call_number)).perform(click());
 
 // Verify that an intent to the dialer was sent with the correct action, phone
 // number and package. Think of Intents intended API as the equivalent to Mockito's verify.
 intended(allOf(
 hasAction(Intent.ACTION_CALL),
 hasData(INTENT_DATA_PHONE_NUMBER),
 toPackage(PACKAGE_ANDROID_DIALER)));
 }
  13. Espresso Intents Intending @Test
 public void pickContactButton_click_SelectsPhoneNumber() {
 // Stub

    all Intents to ContactsActivity to return VALID_PHONE_NUMBER. Note that the Activity
 // is never launched and result is stubbed.
 intending(hasComponent(hasShortClassName(".ContactsActivity")))
 .respondWith(new ActivityResult(Activity.RESULT_OK,
 ContactsActivity.createResultData(VALID_PHONE_NUMBER)));
 
 // Click the pick contact button.
 onView(withId(R.id.button_pick_contact)).perform(click());
 
 // Check that the number is displayed in the UI.
 onView(withId(R.id.edit_text_caller_number))
 .check(matches(withText(VALID_PHONE_NUMBER)));
 }
  14. Espresso Intents Intending @Test
 public void pickContactButton_click_SelectsPhoneNumber() {
 // Stub

    all Intents to ContactsActivity to return VALID_PHONE_NUMBER. Note that the Activity
 // is never launched and result is stubbed.
 intending(hasComponent(hasShortClassName(".ContactsActivity")))
 .respondWith(new ActivityResult(Activity.RESULT_OK,
 ContactsActivity.createResultData(VALID_PHONE_NUMBER)));
 
 // Click the pick contact button.
 onView(withId(R.id.button_pick_contact)).perform(click());
 
 // Check that the number is displayed in the UI.
 onView(withId(R.id.edit_text_caller_number))
 .check(matches(withText(VALID_PHONE_NUMBER)));
 }
  15. Espresso Intents Intending @Test
 public void pickContactButton_click_SelectsPhoneNumber() {
 // Stub

    all Intents to ContactsActivity to return VALID_PHONE_NUMBER. Note that the Activity
 // is never launched and result is stubbed.
 intending(hasComponent(hasShortClassName(".ContactsActivity")))
 .respondWith(new ActivityResult(Activity.RESULT_OK,
 ContactsActivity.createResultData(VALID_PHONE_NUMBER)));
 
 // Click the pick contact button.
 onView(withId(R.id.button_pick_contact)).perform(click());
 
 // Check that the number is displayed in the UI.
 onView(withId(R.id.edit_text_caller_number))
 .check(matches(withText(VALID_PHONE_NUMBER)));
 }
  16. Resources http://chiuki.github.io/advanced-android-espresso Advanced Android Espresso - Chiu-Ki Chan https://www.youtube.com/watch?v=hfoAC9gdC74 https://speakerdeck.com/guardiola31337/elegant-unit-testing-droidcon-spain-2015

    Elegant?? Unit Testing - Pablo Guardiola Android unit and instrumentation tests- Lars Vogel http://www.vogella.com/tutorials/AndroidTesting/article.html http://developer.android.com/intl/es/tools/testing-support-library/index.html