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

Effective Espresso #roppongi_aar

2d8205dc9c77318497ef33ba475817fe?s=47 Rize MISUMI
November 17, 2015

Effective Espresso #roppongi_aar

at Roppongi.aar #2

2d8205dc9c77318497ef33ba475817fe?s=128

Rize MISUMI

November 17, 2015
Tweet

More Decks by Rize MISUMI

Other Decks in Programming

Transcript

  1. Effective Espresso Misumi_Rize Roppongi.aar #2 (Nov. 17, 2015)

  2. Log.d("introduction", me); → Twitter @Misumi_Rize → GitHub @MisumiRize → I'm

    not Android APK developer
  3. My previous presentation

  4. First of all: androidTest != Espresso

  5. Espresso is... → High level wrapper of Instrumentation → High

    level wrapper of InputEvent → View assertion
  6. You can test them with Espresso → View interaction →

    Activity transition
  7. Espresso Pros. → You can stub out unnecessary APIs →

    Simple synchronous interaction API → Built-in matchers
  8. Espresso Cons. → Requires slow simulator or real device →

    Long test problem → Built-in matchers
  9. Use case of Espresso → Activity integration test → Do

    not test everything using Espresso → Avoid writing too many tests using Espresso
  10. Start Using Espresso

  11. build.gradle android { defaultConfig { // ... testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' }

    // ... packagingOptions { exclude 'LICENSE.txt' } } dependencies { // ... androidTestCompile 'com.android.support.test:runner:0.4.1' androidTestCompile 'com.android.support.test:rules:0.4.1' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1' }
  12. Run with JUnit 4 @RunWith(AndroidJUnit4Runner.class) public class MainActivityTest { @Rule

    public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class); @Test public void submitButtonIsDisplayed() { Espresso.onView(ViewMatchers.withId(R.id.submit_button)) .check(ViewAssertions.isDisplayed()); } }
  13. Note → @Rule is just JUnit lifecycle hook → You

    can also launch Activity manually → You can also assert regular JUnit way
  14. Composite ViewMatchers → ViewMatchers.hasText() → ViewMatchers.hasSibling() → allOf(), oneOf()

  15. Capture Intents

  16. build.gradle dependencies { // ... androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1' }

  17. Intent matching @Test public void testTransitingToBrowser() { Espresso.onView(ViewMatchers.withId(R.id.launch_browser)) .perform(ViewActions.click()); Intents.intended(

    Matchers.allOf( IntentMatchers.hasAction(IsEqual.equalTo(Intent.ACTION_VIEW)), IntentMatchers.hasData("https://google.com") ) ); }
  18. Async Handling

  19. build.gradle dependencies { // ... androidTestCompile 'com.android.support.test.espresso:espresso-idling-resource:2.2.1' }

  20. public class MyIdlingResource implements IdlingResource { private ResourceCallback resourceCallback; private

    idle = true; @Override public String getName() { return IntentServiceIdlingResource.class.getName(); } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } @Override public boolean isIdleNow() { if (idle && resourceCallback != null) { resourceCallback.onTransitionToIdle(); } return idle; } public void setIdle(boolean idle) { this.idle = idle; } }
  21. On test @Test public void testHandleAsync() { MyIdlingResource idlingResource =

    new MyIdlingResource(); Espresso.registerIdlingResources(idlingResource); // Do something // Do not forget unregister idlingResource Espresso.unregisterIdlingResources(idlingResource); }
  22. Don't Repeat Yourself

  23. DRY → Separate content from code → Make refactoring easy

  24. @Test public void submitButtonIsDisplayed() { submitButton().check( ViewAssertions.isDisplayed() ); } private

    ViewInteraction submitButton() { return Espresso.onView( ViewMatchers.withText("Submit") ); }
  25. Random Data

  26. Use Faker → More natural user data → Bootstrappable (zip

    code, address) → Internet-friendly (email, domain)
  27. build.gradle dependencies { // ... androidTestCompile 'com.github.javafaker:javafaker:0.6' }

  28. private Faker faker; @Before public void setUp() { faker =

    new Faker(); } @Test public void inputEmailAddress() { editEmailAddress() .perform(ViewActions.sendKeys(emailAddress())); } private String emailAddress() { return faker.internet().emailAddress(); }
  29. Use With Lambda

  30. Lambda on Android → Shorten anonymous class declaration → Retrolambda,

    Kotlin, Groovy
  31. Check with Lambda @Test public void textIsCorrect() { myTextView() .check((View

    view, NoMatchingViewException e) -> if (e != null) { Assert.fail(e.getMessage()); } Assert.assertEquals( ((TextView) view).getText().toString(), "Hello, world" ); }) }
  32. But little dirty hack is needed with Kotlin... private val

    activityRule = ActivityTestRule(MainActivity::class.java) @Rule public fun getActivityRule(): ActivityTestRule<MainActivity> = activityRule
  33. Page Object Pattern?

  34. Does Page Object Pattern adapt? → I think page object

    pattern is too huge → Espresso: Integration test → Selenium (Appium): End-to-end test
  35. Conclusion → Espresso is high level wrapper of Instrumentation →

    There are many tips to make tests solid → Do not test everything using Espresso
  36. → Rocket Espresso Cellini V3 by Scott Schiller