Discovering Android Testing

Discovering Android Testing

Slides for the presentation about Android Testing that i gave for the Pucela Testing Days

A1088f881e7bfd06e45e400d9714c930?s=128

Mario de Frutos

November 30, 2013
Tweet

Transcript

  1. Discovering Testing in android Mario de Frutos @ethervoid sábado, 30

    de noviembre de 13
  2. Mario de Frutos @Ethervoid sábado, 30 de noviembre de 13

  3. Ecosystem Dagger Otto Retrofit sábado, 30 de noviembre de 13

  4. LET’S DO IT sábado, 30 de noviembre de 13

  5. Unit Integration UI Test PYramid sábado, 30 de noviembre de

    13
  6. UNIT TESTING sábado, 30 de noviembre de 13

  7. What is it? A unit test is an automated piece

    of code that invokes a unit of work in the system and then checks a single assumption about the behavior of that unit of work. - The art of unit testing What are we going to test in Android? Business Logic View validation Behavior sábado, 30 de noviembre de 13
  8. Business Logic ‣Better if you make it independent from the

    Android platform ‣Possible to test using JUnit3 ‣Example sábado, 30 de noviembre de 13
  9. View validation ‣Mainly check the view elements are correctly displayed

    View Behavior ‣Check that the view behavior is the expected ¿EXAMPLES?? sábado, 30 de noviembre de 13
  10. Test What type of test should i use? Use only

    the JVM Use Android FW LET’S TRY WITH JUNIT alone... sábado, 30 de noviembre de 13
  11. RuntimeException("Stub!"). sábado, 30 de noviembre de 13

  12. Let’s try ActivityUnitTestCase [ERROR] Failed to execute goal com.jayway.maven.plugins.android.generation2:android-maven-plugin: 3.8.0:internal-pre-integration-test

    (default-internal-pre-integration-test) on project pucelatestingapptest: No online devices attached. @Override        protected  void  setUp()  throws  Exception  {                super.setUp();                Intent  intent  =  new  Intent(getInstrumentation().getTargetContext(),                                MainActivity.class);                startActivity(intent,  null,  null);                activity  =  getActivity();        }        public  void  testRadioOfEurIsMarkedByDefault()  {                RadioButton  radioEurs  =  (RadioButton)  activity.findViewById(R.id.eurs_radio_button);                assertTrue("Eur  radio  button  not  marked  by  default",  radioEurs.isChecked());        } sábado, 30 de noviembre de 13
  13. Robolectric to the rescue! sábado, 30 de noviembre de 13

  14. What is Robolectric? Robolectric is a unit test framework that

    de-fangs the Android SDK jar so you can test- drive the development of your Android app ‣Rewrite the Android SDK classes to be able to load in the JVM ‣Can use resources, themes, etc ‣Use Shadow Objects a.k.a Proxies: 1. Intercept of loading Android SUT 2. Rewrite the body 3. Bind “shadow object” to the new Android object ‣ Is possible to build your own shadow objects sábado, 30 de noviembre de 13
  15. @RunWith(RobolectricTestRunner.class) public  class  MainActivityRobolectricTest  {        private  MainActivity

     activity;        private  Button  convertButton;        private  EditText  amountField;        @Before        public  void  setUp()  {                activity  =  Robolectric.buildActivity(MainActivity.class).create().get();                convertButton  =  (Button)  activity.findViewById(R.id.convert_cash_button);                amountField  =  (EditText)  activity.findViewById(R.id.currency_input_field);        }        @Test        public  void  whenTheActivityIsLoadedTheEurRadioButtonShouldBeChecked()  {                RadioButton  radioButton  =  (RadioButton)  activity.findViewById(R.id.eurs_radio_button);                assertThat(radioButton.isChecked(),  equalTo(true));        } } View VALIDATION sábado, 30 de noviembre de 13
  16. @Test        public  void  whenTheConvertButtonIsPressedTheDetailActivityIsCalled()  {    

               Button  convertButton  =  (Button)  activity.findViewById(R.id.convert_cash_button);                convertButton.performClick();                ShadowActivity  shadowActivity  =  shadowOf(activity);                Intent  startedIntent  =  shadowActivity.getNextStartedActivity();                ShadowIntent  shadowIntent  =  shadowOf(startedIntent); assertThat(shadowIntent.getComponent().getClassName(),   equalTo(DetailActivity.class.getName()));        } @Test        public  void  whenTheConvertButtonIsClickedTheAmountIsSentToTheNextActivity()  {                amountField.setText("10");                convertButton.performClick();                ShadowActivity  shadowActivity  =  shadowOf(activity);                Intent  startedIntent  =  shadowActivity.getNextStartedActivity();                ShadowIntent  shadowIntent  =  shadowOf(startedIntent);                assertThat((String)  shadowIntent.getExtras().get("amount"),  equalTo("10"));        } View Behavior sábado, 30 de noviembre de 13
  17. DAGGER sábado, 30 de noviembre de 13

  18. DAGGER ‣No reflection ‣Lazy<T> ‣Module overrides sábado, 30 de noviembre

    de 13
  19. INTEGRATION TESTS sábado, 30 de noviembre de 13

  20. ActivityInstrumentationTestCase2 ‣Most basic integration test ‣Implements instrumentation to control ‣RunOnUIThread

    ‣Small, Medium and Large tests ‣Specific tests for Provider and Services sábado, 30 de noviembre de 13
  21. TYPE OF TESTS Running all small tests: adb shell am

    instrument -w - e size small com.android.foo/ android.test.InstrumentationTestRunner Running all medium tests: adb shell am instrument - w -e size medium com.android.foo/ android.test.InstrumentationTestRunner Running all large tests: adb shell am instrument -w - e size large com.android.foo/ android.test.InstrumentationTestRunner Source: http://googletesting.blogspot.com.es/2010/12/test-sizes.html sábado, 30 de noviembre de 13
  22. @Override protected  void  setUp()  throws  Exception  {      

     super.setUp();        setActivityInitialTouchMode(false);        activity  =  (MainActivity)  getActivity(); } public  void  testThatSettedAnAmountGoToDetailActivityAndShowsThatAmountConverted()  {        ActivityMonitor  monitor  =  getInstrumentation().addMonitor(DetailActivity.class.getName(),null,  false);        final  EditText  amountField  =  (EditText)  activity.findViewById(R.id.currency_input_field);        final  Button  convertButton  =  (Button)  activity.findViewById(R.id.convert_cash_button);        activity.runOnUiThread(new  Runnable()  {                @Override                public  void  run()  {                        amountField.setText("10");                        convertButton.performClick();                }        });        DetailActivity  startedActivity  =  (DetailActivity)  monitor.waitForActivityWithTimeout(5000);        assertNotNull(startedActivity);        TextView  convertAmountText  =  (TextView)  startedActivity.findViewById(R.id.amount_converted);        assertEquals("7.4",  convertAmountText.getText()); } EXAMPLE sábado, 30 de noviembre de 13
  23. ESPRESSO ‣No waits, sleeps, syncs... ‣Used by over 30 apps

    within Google ‣But for early adopters sábado, 30 de noviembre de 13
  24. public  void  testThatSettedAnAmountGoToDetailActivityAndShowsThatAmountConverted()   {          

         onView(withId(R.id.currency_input_field)).perform(typeText("10"));                onView(withId(R.id.convert_cash_button)).perform(click());                onView(withId(R.id.amount_converted)).check(matches(withText("7.4")));                assertTrue(true);        } EXAMPLES onData(allOf(is(instanceOf(String.class)), is("Americano"))) .perform(click()); sábado, 30 de noviembre de 13
  25. OTHER TOOLS ‣Robotium (https://code.google.com/p/robotium/) ‣Monkey ‣Spoon (http://square.github.io/spoon/) ‣Fest (http://square.github.io/fest-android/) ‣Calabash

    (http://calaba.sh/) ‣Appium (http://appium.io/) sábado, 30 de noviembre de 13
  26. QUESTIONS? sábado, 30 de noviembre de 13

  27. ‣http://www.flickr.com/photos/60648084@N00/3930418061 ‣http://www.therawdivas.com/HHH/images/ecoearth.jpg ‣http://www.flickr.com/photos/8344872@N05/4734876946/" ‣http://www.flickr.com/photos/12836528@N00/3249700433 ‣http://www.flickr.com/photos/19387816@N00/229929406 ‣http://www.flickr.com/photos/22490717@N02/4337754798 ‣http://www.flickr.com/photos/35468148654@N01/501445202 ‣http://www.flickr.com/photos/81875138@N00/2829427342/ RESOURCES sábado,

    30 de noviembre de 13