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

Robotium vs Espresso DroidconFr 2014

Thomas Guerin
September 23, 2014

Robotium vs Espresso DroidconFr 2014

Thomas Guerin

September 23, 2014
Tweet

More Decks by Thomas Guerin

Other Decks in Programming

Transcript

  1. Robotium vs Espresso : Get ready to rumble ! Pourquoi

    ne pas faire de tests ? #Droidcon #Robotium #Espresso @Tom404_
  2. Robotium vs Espresso : Get ready to rumble ! Pourquoi

    ne pas faire de tests ? “Mes tests durent des heures !” #Droidcon #Robotium #Espresso @Tom404_
  3. Robotium vs Espresso : Get ready to rumble ! Pourquoi

    ne pas faire de tests ? “Mes tests durent des heures !” #Droidcon #Robotium #Espresso “Tester ce n’est pas toujours simple !” @Tom404_
  4. Robotium vs Espresso : Get ready to rumble ! Pourquoi

    ne pas faire de tests ? “Mes tests durent des heures !” #Droidcon #Robotium #Espresso “Tester ce n’est pas toujours simple !” “Mes tests échouent aléatoirement !” @Tom404_
  5. Robotium vs Espresso : Get ready to rumble ! Pourquoi

    ne pas faire de tests ? “Mes tests durent des heures !” #Droidcon #Robotium #Espresso “Tester ce n’est pas toujours simple !” “Mes tests échouent aléatoirement !” “Je vais devoir corriger les tests alors que je n’ai presque rien modifié” @Tom404_
  6. Robotium vs Espresso : Get ready to rumble ! Un

    test doit être… #Droidcon #Robotium #Espresso @Tom404_
  7. Robotium vs Espresso : Get ready to rumble ! Un

    test doit être… #Droidcon #Robotium #Espresso Simple @Tom404_
  8. Robotium vs Espresso : Get ready to rumble ! Un

    test doit être… #Droidcon #Robotium #Espresso Rapide Simple @Tom404_
  9. Robotium vs Espresso : Get ready to rumble ! Un

    test doit être… #Droidcon #Robotium #Espresso Rapide Simple Fiable @Tom404_
  10. Robotium vs Espresso : Get ready to rumble ! Un

    test doit être… #Droidcon #Robotium #Espresso Rapide Simple Fiable Durable @Tom404_
  11. Robotium vs Espresso : Get ready to rumble ! Un

    mauvais exemple #Droidcon #Robotium #Espresso @Tom404_
  12. Robotium vs Espresso : Get ready to rumble ! Un

    mauvais exemple #Droidcon #Robotium #Espresso // Start the main activity of the application under test mActivity = getActivity(); ! // Get a handle to the Activity object's main UI widget, a Spinner mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01); ! // Set the Spinner to a known position mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION); ! // Stop the activity - The onDestroy() method should save the state of the Spinner mActivity.finish(); ! // Re-start the Activity - the onResume() method should restore the state of the Spinner mActivity = getActivity(); ! // Get the Spinner's current position int currentPosition = mActivity.getSpinnerPosition(); ! // Assert that the current position is the same as the starting position assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition); @Tom404_
  13. Robotium vs Espresso : Get ready to rumble ! Un

    mauvais exemple #Droidcon #Robotium #Espresso // Start the main activity of the application under test mActivity = getActivity(); ! // Get a handle to the Activity object's main UI widget, a Spinner mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01); ! // Set the Spinner to a known position mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION); ! // Stop the activity - The onDestroy() method should save the state of the Spinner mActivity.finish(); ! // Re-start the Activity - the onResume() method should restore the state of the Spinner mActivity = getActivity(); ! // Get the Spinner's current position int currentPosition = mActivity.getSpinnerPosition(); ! // Assert that the current position is the same as the starting position assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition); @Tom404_
  14. Robotium vs Espresso : Get ready to rumble ! Les

    combattants #Droidcon #Robotium #Espresso @Tom404_
  15. Robotium vs Espresso : Get ready to rumble ! Les

    combattants #Droidcon #Robotium #Espresso Robotium @Tom404_
  16. Robotium vs Espresso : Get ready to rumble ! Les

    combattants #Droidcon #Robotium #Espresso VS Robotium Espresso @Tom404_
  17. Robotium vs Espresso : Get ready to rumble ! Dépendances

    Gradle #Droidcon #Robotium #Espresso @Tom404_
  18. Robotium vs Espresso : Get ready to rumble ! Dépendances

    Gradle #Droidcon #Robotium #Espresso dependencies { androidTestCompile ‘com.jayway.android.robotium:robotium-solo:5.2.1' androidTestCompile 'com.squareup.assertj:assertj-android:1.0.0' } Robotium @Tom404_
  19. Robotium vs Espresso : Get ready to rumble ! Dépendances

    Gradle #Droidcon #Robotium #Espresso android.packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' } dependencies { /* Jars récupérés depuis https://code.google.com/p/android-test-kit */ androidTestCompile files(‘libs/espresso-1.1.jar’, ‘libs/espresso-contrib-1.1.jar', ‘libs/testrunner-1.1.jar', 'libs/testrunner-runtime-1.1.jar') androidTestCompile 'com.google.guava:guava:14.0.1', 'com.squareup.dagger:dagger:1.1.0', 'org.hamcrest:hamcrest-core:1.1', 'org.hamcrest:hamcrest-integration:1.1', 'org.hamcrest:hamcrest-library:1.1' } Espresso @Tom404_
  20. Robotium vs Espresso : Get ready to rumble ! Dépendances

    Gradle #Droidcon #Robotium #Espresso android.packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' } dependencies { androidTestCompile ’com.jakewharton.espresso:espresso:1.1-r3’, ‘com.jakewharton.espresso:espresso-support-v4:1.1-r3' } https://github.com/JakeWharton/double-espresso Double Espresso @Tom404_
  21. Robotium vs Espresso : Get ready to rumble ! Test

    Runner #Droidcon #Robotium #Espresso @Tom404_
  22. Robotium vs Espresso : Get ready to rumble ! Test

    Runner #Droidcon #Robotium #Espresso Robotium utilise le test runner du sdk @Tom404_
  23. Robotium vs Espresso : Get ready to rumble ! Test

    Runner #Droidcon #Robotium #Espresso Robotium utilise le test runner du sdk Espresso nécessite un test runner spécifique @Tom404_
  24. Robotium vs Espresso : Get ready to rumble ! Test

    Runner #Droidcon #Robotium #Espresso Robotium utilise le test runner du sdk Espresso nécessite un test runner spécifique defaultConfig { testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner" } @Tom404_
  25. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner

    #Droidcon #Robotium #Espresso onCreate de l'application finalisée avant le début des tests @Tom404_
  26. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner

    #Droidcon #Robotium #Espresso onCreate de l'application finalisée avant le début des tests Instrumentation terminée == activités finies @Tom404_
  27. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner

    #Droidcon #Robotium #Espresso onCreate de l'application finalisée avant le début des tests Instrumentation terminée == activités finies Monitoring des activités plus fiable @Tom404_
  28. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner

    #Droidcon #Robotium #Espresso onCreate de l'application finalisée avant le début des tests Instrumentation terminée == activités finies Monitoring des activités plus fiable Peut être utilisé avec d'autres librairies @Tom404_
  29. Robotium vs Espresso : Get ready to rumble ! Initialisation

    #Droidcon #Robotium #Espresso @Tom404_
  30. Robotium vs Espresso : Get ready to rumble ! Initialisation

    #Droidcon #Robotium #Espresso Robotium public class SimpleActionsTest extends ActivityInstrumentationTestCase2<MainActivity> { ! private Solo solo; ! public void setUp() throws Exception { super.setUp(); solo = new Solo(getInstrumentation(), getActivity()); } ! public void tearDown() throws Exception { solo.finishOpenedActivities(); super.tearDown(); } } @Tom404_
  31. Robotium vs Espresso : Get ready to rumble ! Initialisation

    #Droidcon #Robotium #Espresso public class SimpleActionsTest extends ActivityInstrumentationTestCase2<MainActivity> { ! @Override protected void setUp() throws Exception { super.setUp(); // Espresso ne va pas lancer l'activité pour nous getActivity(); } } Espresso @Tom404_
  32. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso Robotium @Tom404_
  33. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso Solo Robotium @Tom404_
  34. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso Solo getView(int viewId) drag(…) clickInList(int line, int index) goBack() setNavigationDrawer(int status) pressSoftKeyboardNextButton( clickOnActionBarItem(int id) scrollToBottom() searchEditText(String text) pressSoftKeyboardSearchButton() getButton(int index) scrollDown() clearEditText(int index) clickOnToggleButton(String text) clickOnImageButton(int index) clickOnButton(int index) pressMenuItem(int index) clickOnActionBarHome() scrollDownList(int index) searchText(String text) @Tom404_
  35. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso @Tom404_
  36. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso // Récupération de la vue Button myButton = (TextView) solo.getView(R.id.my_button); ! // Assertions (AssertJ Android) assertThat(myButton).hasText(“My button”).isVisible(); ! // Clic sur la vue solo.clickOnView(myButton) @Tom404_
  37. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    #Droidcon #Robotium #Espresso @Tom404_
  38. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    #Droidcon #Robotium #Espresso Librairie de matchers @Tom404_
  39. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    #Droidcon #Robotium #Espresso Librairie de matchers assertThat("Hello", equalTo("Hello")) @Tom404_
  40. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    #Droidcon #Robotium #Espresso Librairie de matchers assertThat("Hello", equalTo("Hello")) ! // Sucre syntaxique assertThat(“Hello", is("Hello")) @Tom404_
  41. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    #Droidcon #Robotium #Espresso Librairie de matchers assertThat("Hello", equalTo("Hello")) ! // Sucre syntaxique assertThat(“Hello", is("Hello")) ! // De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase @Tom404_
  42. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    #Droidcon #Robotium #Espresso Librairie de matchers assertThat("Hello", equalTo("Hello")) ! // Sucre syntaxique assertThat(“Hello", is("Hello")) Possibilité de composition ! // De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase @Tom404_
  43. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    custom matcher #Droidcon #Robotium #Espresso @Tom404_
  44. Robotium vs Espresso : Get ready to rumble ! Hamcrest

    custom matcher #Droidcon #Robotium #Espresso public class IsNotANumber extends TypeSafeMatcher<Double> { ! @Override public boolean matchesSafely(Double number) { return number.isNaN(); } ! public void describeTo(Description description) { description.appendText("not a number"); } ! public static Matcher<Double> notANumber() { return new IsNotANumber(); } ! } @Tom404_
  45. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso Espresso @Tom404_
  46. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso Espresso @Tom404_
  47. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso withId()! withText(text)! hasSibling(Matcher<View>) ViewMatchers Espresso @Tom404_
  48. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso click()! typeText(text) ViewActions withId()! withText(text)! hasSibling(Matcher<View>) ViewMatchers Espresso @Tom404_
  49. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso click()! typeText(text) ViewActions doesNotExist()! matches(Matcher<View>) ViewAssertions withId()! withText(text)! hasSibling(Matcher<View>) ViewMatchers Espresso @Tom404_
  50. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso perform(ViewAction)! check(ViewAssertion) ViewInteraction / DataInteraction click()! typeText(text) ViewActions doesNotExist()! matches(Matcher<View>) ViewAssertions withId()! withText(text)! hasSibling(Matcher<View>) ViewMatchers Espresso @Tom404_
  51. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso perform(ViewAction)! check(ViewAssertion) ViewInteraction / DataInteraction click()! typeText(text) ViewActions doesNotExist()! matches(Matcher<View>) ViewAssertions withId()! withText(text)! hasSibling(Matcher<View>) ViewMatchers Espresso @Tom404_
  52. Robotium vs Espresso : Get ready to rumble ! API

    overview #Droidcon #Robotium #Espresso onView(Matcher<View>)! onData(Matcher<Object> Espresso perform(ViewAction)! check(ViewAssertion) ViewInteraction / DataInteraction click()! typeText(text) ViewActions doesNotExist()! matches(Matcher<View>) ViewAssertions withId()! withText(text)! hasSibling(Matcher<View>) ViewMatchers Espresso @Tom404_
  53. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso @Tom404_
  54. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click()); @Tom404_
  55. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click()); ! // Une simple extraction de méthode permet de simplifier onView(withIdAndText(R.id.my_button, "My Button”)) .check(matches(isDisplayed())) .perform(click()); @Tom404_
  56. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click()); ! // Une simple extraction de méthode permet de simplifier onView(withIdAndText(R.id.my_button, "My Button”)) .check(matches(isDisplayed())) .perform(click()); ! // Si le bouton n'est pas affiché le perform(click()) échouera onView(withIdAndText(R.id.my_button, "My Button")).perform(click()); @Tom404_
  57. Robotium vs Espresso : Get ready to rumble ! Exemple

    #Droidcon #Robotium #Espresso onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click()); Manque de restrictions = AmbiguousViewMatcherException ! // Une simple extraction de méthode permet de simplifier onView(withIdAndText(R.id.my_button, "My Button”)) .check(matches(isDisplayed())) .perform(click()); ! // Si le bouton n'est pas affiché le perform(click()) échouera onView(withIdAndText(R.id.my_button, "My Button")).perform(click()); @Tom404_
  58. Robotium vs Espresso : Get ready to rumble ! Listview

    #Droidcon #Robotium #Espresso @Tom404_
  59. Robotium vs Espresso : Get ready to rumble ! Listview

    #Droidcon #Robotium #Espresso // Clic sur item solo.clickOnText("textToFind"); ! // Si jamais il y'en a plusieurs -> utilisation d'un index solo.clickOnText("textToFind", 3); ! // Ou choisir directement la ligne solo.clickInList(2); Robotium @Tom404_
  60. Robotium vs Espresso : Get ready to rumble ! Listview

    #Droidcon #Robotium #Espresso onData(allOf(is(instanceOf(String.class)), is("textToFind"))).perform(click()); ! // Ou directement à une position onData(is(instanceOf(String.class))).atPosition(0).perform(click()); ! // Possibilité de préciser une listview, utile pour le view pager onData(allOf(is(instanceOf(String.class)), is("textToFind"))) .inAdapterView(withId(R.id.my_list)).perform(click()); ! // Interaction avec une vue enfant de la ligne onData(allOf(is(instanceOf(String.class)), is("textToFind"))) .onChildView(withId(R.id.my_child)) .perform(click()); Espresso @Tom404_
  61. Robotium vs Espresso : Get ready to rumble ! Listview

    #Droidcon #Robotium #Espresso // Type renvoyé par la méthode getItem de l'adapteur public class Item { public String name; public String itemContent; } Espresso : cas plus complexe ! onData(allOf(is(instanceOf(Item.class)), hasProperty(“name", equalTo(“nameToFind")))) .perform(click()); @Tom404_
  62. Robotium vs Espresso : Get ready to rumble ! Listview

    #Droidcon #Robotium #Espresso public static Matcher<Object> withItemName(final Matcher<String> itemTextMatcher){ return new BoundedMatcher<Object, Item>(Item.class) { @Override public boolean matchesSafely(Item item) { return itemTextMatcher.matches(item.name); } ! @Override public void describeTo(Description description) { description.appendText("with item name: "); itemTextMatcher.describeTo(description); } }; } Espresso : custom matcher onData(withItemName(equalTo("nameToFind"))).perform(click()); @Tom404_
  63. Robotium vs Espresso : Get ready to rumble ! Webview

    #Droidcon #Robotium #Espresso Robotium @Tom404_
  64. Robotium vs Espresso : Get ready to rumble ! Webview

    #Droidcon #Robotium #Espresso Robotium Possibilité d’interagir avec les webviews •solo.getWebElements(by) •solo.clickOnWebElement(by) @Tom404_
  65. Robotium vs Espresso : Get ready to rumble ! Webview

    #Droidcon #Robotium #Espresso Robotium Possibilité d’interagir avec les webviews •solo.getWebElements(by) •solo.clickOnWebElement(by) Plusieurs types de recherches disponibles •By.id(String id) •By.className(String className) •By.textContent(String textContent) •By.name(String name) @Tom404_
  66. Robotium vs Espresso : Get ready to rumble ! Webview

    #Droidcon #Robotium #Espresso Espresso @Tom404_
  67. Robotium vs Espresso : Get ready to rumble ! Webview

    #Droidcon #Robotium #Espresso Espresso @Tom404_
  68. Robotium vs Espresso : Get ready to rumble ! Navigation

    Drawer #Droidcon #Robotium #Espresso @Tom404_
  69. Robotium vs Espresso : Get ready to rumble ! Navigation

    Drawer #Droidcon #Robotium #Espresso Robotium // Attention l'id du frame layout du menu doit absolument être "left_drawer" solo.setNavigationDrawer(Solo.OPENED); ! solo.setNavigationDrawer(Solo.CLOSED); @Tom404_
  70. Robotium vs Espresso : Get ready to rumble ! Navigation

    Drawer #Droidcon #Robotium #Espresso Robotium // Attention l'id du frame layout du menu doit absolument être "left_drawer" solo.setNavigationDrawer(Solo.OPENED); ! solo.setNavigationDrawer(Solo.CLOSED); Espresso DrawerActions.openDrawer(R.id.drawer_layout); ! DrawerActions.closeDrawer(R.id.drawer_layout); @Tom404_
  71. Robotium vs Espresso : Get ready to rumble ! Action

    bar #Droidcon #Robotium #Espresso @Tom404_
  72. Robotium vs Espresso : Get ready to rumble ! Action

    bar #Droidcon #Robotium #Espresso Robotium solo.clickOnActionBarItem(R.id.action_example); ! // Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action"); @Tom404_
  73. Robotium vs Espresso : Get ready to rumble ! Action

    bar #Droidcon #Robotium #Espresso Robotium solo.clickOnActionBarItem(R.id.action_example); ! // Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action"); Espresso onView(withId(R.id_action_example)).perform(click()); ! // Cas de l'action bar overflow openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); onView(withText("action")).perform(click()); @Tom404_
  74. Robotium vs Espresso : Get ready to rumble ! Back

    button & Keyboard #Droidcon #Robotium #Espresso @Tom404_
  75. Robotium vs Espresso : Get ready to rumble ! Back

    button & Keyboard #Droidcon #Robotium #Espresso Robotium solo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier @Tom404_
  76. Robotium vs Espresso : Get ready to rumble ! Back

    button & Keyboard #Droidcon #Robotium #Espresso Robotium solo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier Espresso Espresso.pressBack(); Espresso.closeSoftKeyboard(); @Tom404_
  77. Robotium vs Espresso : Get ready to rumble ! Les

    messages d’erreur #Droidcon #Robotium #Espresso @Tom404_
  78. Robotium ! junit.framework.AssertionFailedError: View with id: '1234' is not found!

    at com.robotium.solo.Solo.getView(Solo.java:2008) at com.robotium.solo.Solo.getView(Solo.java:1988) at fr.droidcon.robotium.vs.espresso.samples.test.robotium.SimpleActionsTest.testClickButton(SimpleAct ionsTest.java:28) ! // Récupération d’une vue inexistante solo.getView(1234); Robotium vs Espresso : Get ready to rumble ! Les messages d’erreur #Droidcon #Robotium #Espresso @Tom404_
  79. com.google.android.apps.common.testing.ui.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: is

    <1234> If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:android.widget.ListView{426f6f18 VFED.VC. ......ID 0,0-720,1557} - android.widget.ListView{4269c598 V.ED.VC. ........ 48,393-1032,1509 #7f070042 app:id/my_list} ! View Hierarchy: +>DecorView{id=-1, visibility=VISIBLE, width=1080, height=1776, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is- layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1} | +->ActionBarOverlayLayout{id=16909075, res-name=action_bar_overlay_layout, visibility=VISIBLE, width=1080, height=1776, has-focus=true, has-focusable=true, has-window-focus=true, is- clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is- selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child- count=3} | +-->FrameLayout{id=16908290, res-name=content, visibility=VISIBLE, width=1080, height=1557, Espresso ! // Récupération d’une vue inexistante onView(withId(1234)); Robotium vs Espresso : Get ready to rumble ! Les messages d’erreur #Droidcon #Robotium #Espresso @Tom404_
  80. Robotium vs Espresso : Get ready to rumble ! Wait

    and See #Droidcon #Robotium #Espresso @Tom404_
  81. Robotium vs Espresso : Get ready to rumble ! Wait

    and See #Droidcon #Robotium #Espresso Robotium repose sur le principe de wait & see •solo.waitForActivity(Class class, int timeout) •solo.waitForCondition(Condition condition, int timeout) •solo.waitForDialogToOpen() @Tom404_
  82. Robotium vs Espresso : Get ready to rumble ! Wait

    and See #Droidcon #Robotium #Espresso solo.clickOnView(R.id.start_activity_button); ! // On attend que la vue apparaisse avant d'agir solo.waitForView(R.id.view_in_new_activity); ! solo.clickOnView(R.id.view_in_new_activity); Robotium repose sur le principe de wait & see •solo.waitForActivity(Class class, int timeout) •solo.waitForCondition(Condition condition, int timeout) •solo.waitForDialogToOpen() @Tom404_
  83. Robotium vs Espresso : Get ready to rumble ! Finis

    de dormir ! #Droidcon #Robotium #Espresso @Tom404_
  84. Robotium vs Espresso : Get ready to rumble ! Finis

    de dormir ! #Droidcon #Robotium #Espresso Entrée en jeu du GoogleInstrumentationTestRunner @Tom404_
  85. Robotium vs Espresso : Get ready to rumble ! Finis

    de dormir ! #Droidcon #Robotium #Espresso Entrée en jeu du GoogleInstrumentationTestRunner Monitoring plus fin des activités et des ressources @Tom404_
  86. Robotium vs Espresso : Get ready to rumble ! Finis

    de dormir ! #Droidcon #Robotium #Espresso Entrée en jeu du GoogleInstrumentationTestRunner Monitoring plus fin des activités et des ressources Analyse du ThreadUI pour savoir quand agir @Tom404_
  87. Robotium vs Espresso : Get ready to rumble ! Finis

    de dormir ! #Droidcon #Robotium #Espresso Entrée en jeu du GoogleInstrumentationTestRunner Monitoring plus fin des activités et des ressources Analyse du ThreadUI pour savoir quand agir Pas de wait @Tom404_
  88. Robotium vs Espresso : Get ready to rumble ! Finis

    de dormir ! #Droidcon #Robotium #Espresso onView(withId(R.id.start_activity_button)).perform(click()); ! onView(withId(R.id.view_in_new_activity)).perform(click()); Entrée en jeu du GoogleInstrumentationTestRunner Monitoring plus fin des activités et des ressources Analyse du ThreadUI pour savoir quand agir Pas de wait @Tom404_
  89. Robotium vs Espresso : Get ready to rumble ! Idle

    mais actif ! #Droidcon #Robotium #Espresso @Tom404_
  90. Robotium vs Espresso : Get ready to rumble ! Idle

    mais actif ! #Droidcon #Robotium #Espresso Possibilité d'enregistrer des idlingResources @Tom404_
  91. Robotium vs Espresso : Get ready to rumble ! #Droidcon

    #Robotium #Espresso class EspressoThreadPool extends ThreadPoolExecutor implements IdlingResource { private int threadCount = 0; private ResourceCallback resourceCallback; ... @Override public synchronized void execute(Runnable r) { threadCount++; super.execute(r); } @Override public synchronized boolean isIdleNow() { return threadCount == 0; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } @Override protected synchronized void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); threadCount--; if (resourceCallback != null && isIdleNow()) { resourceCallback.onTransitionToIdle(); } } } @Tom404_
  92. Robotium vs Espresso : Get ready to rumble ! #Droidcon

    #Robotium #Espresso class EspressoThreadPool extends ThreadPoolExecutor implements IdlingResource { private int threadCount = 0; private ResourceCallback resourceCallback; ... @Override public synchronized void execute(Runnable r) { threadCount++; super.execute(r); } @Override public synchronized boolean isIdleNow() { return threadCount == 0; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } @Override protected synchronized void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); threadCount--; if (resourceCallback != null && isIdleNow()) { resourceCallback.onTransitionToIdle(); } } } Espresso.registerIdlingResources(espressoThreadPool); @Tom404_