Slide 1

Slide 1 text

Discovering Testing in android Mario de Frutos @ethervoid sábado, 30 de noviembre de 13

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

UNIT TESTING sábado, 30 de noviembre de 13

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

RuntimeException("Stub!"). sábado, 30 de noviembre de 13

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Robolectric to the rescue! sábado, 30 de noviembre de 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

@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

Slide 16

Slide 16 text

@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

Slide 17

Slide 17 text

DAGGER sábado, 30 de noviembre de 13

Slide 18

Slide 18 text

DAGGER ‣No reflection ‣Lazy ‣Module overrides sábado, 30 de noviembre de 13

Slide 19

Slide 19 text

INTEGRATION TESTS sábado, 30 de noviembre de 13

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

@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

Slide 23

Slide 23 text

ESPRESSO ‣No waits, sleeps, syncs... ‣Used by over 30 apps within Google ‣But for early adopters sábado, 30 de noviembre de 13

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

QUESTIONS? sábado, 30 de noviembre de 13

Slide 27

Slide 27 text

‣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