BABBQ5 - Automated Testing for Modern Android Applications

E0ac1256093c733a5d5a26085b90966f?s=47 Andy Dyer
October 17, 2014

BABBQ5 - Automated Testing for Modern Android Applications

How to use dependency injection, mocking, and a test runner to automate UI & unit testing. Sample app source on GitHub: https://github.com/abdyer/android-test-demo

E0ac1256093c733a5d5a26085b90966f?s=128

Andy Dyer

October 17, 2014
Tweet

Transcript

  1. 3.
  2. 13.

    DEPENDENCY INJECTION ▸ Decouples application components ▸ Classes receive dependencies,

    don’t have to know where to find them or how to create them ▸ Makes it easy to swap components for mocks in tests
  3. 14.

    BASIC DEPENDENCY INJECTION public class Beer { Water water; Barley

    barley; Hops hops; public Beer(Water water, Barley barley, Hops hops) { this.water = water; this.barley = barley; this.hops = hops; } }
  4. 16.

    DAGGER ▸ Define dependencies at compile time to avoid reflection

    at runtime ▸ Compiler validates modules and injections ▸ Jake Wharton “Architecting Android Applications with Dagger" goo.gl/JIM7KI square.github.io/dagger
  5. 17.

    DAGGER MODULES @Module(injects = {MyActivity.class, MyFragment.class}) public class MyModule {

    @Provides @Singleton public MyService provideMyService() { return new MyService(); } }
  6. 18.

    DAGGER OBJECT GRAPH public class MyApplication extends Application { private

    dagger.ObjectGraph objectGraph; @Getter static MyApplication instance; @Override public void onCreate() { super.onCreate(); instance = this; objectGraph = dagger.ObjectGraph.create(new MyModule()); } public void inject(Object dependent) { objectGraph.inject(dependent); } }
  7. 19.

    DAGGER DEPENDENCY INJECTION public class MyFragment extends Fragment { @Inject

    MyService service; @Override public void onViewCreated(View view, Bundle savedInstanceState) { MyApplication.getInstance().inject(this); service.getMyData(); } }
  8. 21.

    MOCKING & STUBBING ▸ Substitute runtime implementation for something that

    can be predictably tested in isolation ▸ Verify behavior
  9. 23.

    MOCKITO ▸ Mock/stub dependencies and function return values ▸ Inject

    mocks to validate behavior in tests ▸ Use included Hamcrest matchers for clear, readable tests code.google.com/p/mockito/
  10. 24.

    USING MOCKITO MyClass mocked = mock(MyClass.class); // code to inject

    mock & load activity/fragment // ... verify(mocked).getMyData(anyInt(), anyString());
  11. 28.

    ESPRESSO ▸ Handles activity creation & state sync ▸ Simple,

    concise API ▸ Really fast! code.google.com/p/android-test-kit
  12. 29.

    USING ESPRESSO public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity> { public MyActivityTest()

    { super(MyActivity.class); } @Override protected void setUp() throws Exception { super.setUp(); getActivity(); // trigger activity launch } public void testInvalidEmailShowsError() { onView(withId(R.id.email)).perform(typeText("abc"), closeSoftKeyboard()); onView(withId(R.id.email_sign_in_button)).perform(click()); onView(withId(R.id.email)).check(matches(withError( getActivity().getString(R.string.error_invalid_email)))); } }
  13. 30.

    SAMPLE APPLICATION OVERVIEW ▸ Retrofit API with sample requests ▸

    Dagger module ▸ Lombok & Android Studio plugin ▸ Login activity ▸ Activity with list fragment to make API request and display data