DroidCon 2014 - Robotium vs espresso_droidcon

519 vues

Publié le

Vos tests Robotium sont instables ? Peu lisibles ? Alors venez découvrir Espresso, la nouvelle librairie de testing pour Android.
Présentation proposée par Thomas Guérin lors de la DroidCon Fr 2014

Publié dans : Technologie
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
519
Sur SlideShare
0
Issues des intégrations
0
Intégrations
2
Actions
Partages
0
Téléchargements
7
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

DroidCon 2014 - Robotium vs espresso_droidcon

  1. 1. Robotiumvs Espresso Get ready to rumble !
  2. 2. Thomas Guerin
  3. 3. Thomas Guerin Développeur Android
  4. 4. Thomas Guerin Développeur Android Tests addict
  5. 5. Thomas Guerin Développeur Android Tests addict Niveau 15 à Destiny
  6. 6. Robotium vs Espresso : Get ready to rumble !
  7. 7. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? #Droidcon #Robotium #Espresso @Tom404_
  8. 8. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? “Mes tests durent des heures !” #Droidcon #Robotium #Espresso @Tom404_
  9. 9. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? “Mes tests durent des heures !” “Tester ce n’est pas toujours simple !” #Droidcon #Robotium #Espresso @Tom404_
  10. 10. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? “Mes tests durent des heures !” “Tester ce n’est pas toujours simple !” “Mes tests échouent aléatoirement !” #Droidcon #Robotium #Espresso @Tom404_
  11. 11. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? “Mes tests durent des heures !” “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é” #Droidcon #Robotium #Espresso @Tom404_
  12. 12. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  13. 13. Robotium vs Espresso : Get ready to rumble ! Un test doit être… #Droidcon #Robotium #Espresso @Tom404_
  14. 14. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple #Droidcon #Robotium #Espresso @Tom404_
  15. 15. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple Rapide #Droidcon #Robotium #Espresso @Tom404_
  16. 16. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple Rapide Fiable #Droidcon #Robotium #Espresso @Tom404_
  17. 17. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple Rapide Fiable Durable #Droidcon #Robotium #Espresso @Tom404_
  18. 18. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  19. 19. Robotium vs Espresso : Get ready to rumble ! Un mauvais exemple #Droidcon #Robotium #Espresso @Tom404_
  20. 20. Robotium vs Espresso : Get ready to rumble ! Un mauvais exemple // 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); #Droidcon #Robotium #Espresso @Tom404_
  21. 21. Robotium vs Espresso : Get ready to rumble ! Un mauvais exemple // 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); #Droidcon #Robotium #Espresso @Tom404_
  22. 22. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  23. 23. Robotium vs Espresso : Get ready to rumble ! Les combattants #Droidcon #Robotium #Espresso @Tom404_
  24. 24. Robotium vs Espresso : Get ready to rumble ! Les combattants Robotium #Droidcon #Robotium #Espresso @Tom404_
  25. 25. Robotium vs Espresso : Get ready to rumble ! Les combattants #Droidcon #Robotium #Espresso VS Robotium Espresso @Tom404_
  26. 26. Préparation
  27. 27. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  28. 28. Robotium vs Espresso : Get ready to rumble ! Dépendances Gradle #Droidcon #Robotium #Espresso @Tom404_
  29. 29. Robotium vs Espresso : Get ready to rumble ! Dépendances Gradle Robotium dependencies { androidTestCompile ‘com.jayway.android.robotium:robotium-solo:5.2.1' androidTestCompile 'com.squareup.assertj:assertj-android:1.0.0' } #Droidcon #Robotium #Espresso @Tom404_
  30. 30. Robotium vs Espresso : Get ready to rumble ! Dépendances Gradle Espresso 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' } android.packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' } #Droidcon #Robotium #Espresso @Tom404_
  31. 31. Robotium vs Espresso : Get ready to rumble ! Dépendances Gradle Double Espresso dependencies { androidTestCompile ’com.jakewharton.espresso:espresso:1.1-r3’, ‘com.jakewharton.espresso:espresso-support-v4:1.1-r3' } android.packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' } https://github.com/JakeWharton/double-espresso #Droidcon #Robotium #Espresso @Tom404_
  32. 32. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  33. 33. Robotium vs Espresso : Get ready to rumble ! Test Runner #Droidcon #Robotium #Espresso @Tom404_
  34. 34. Robotium vs Espresso : Get ready to rumble ! Test Runner Robotium utilise le test runner du sdk #Droidcon #Robotium #Espresso @Tom404_
  35. 35. Robotium vs Espresso : Get ready to rumble ! Test Runner Robotium utilise le test runner du sdk Espresso nécessite un test runner spécifique #Droidcon #Robotium #Espresso @Tom404_
  36. 36. Robotium vs Espresso : Get ready to rumble ! Test Runner 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" } #Droidcon #Robotium #Espresso @Tom404_
  37. 37. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  38. 38. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner #Droidcon #Robotium #Espresso @Tom404_
  39. 39. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner onCreate de l'application finalisée avant le début des tests #Droidcon #Robotium #Espresso @Tom404_
  40. 40. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner onCreate de l'application finalisée avant le début des tests Instrumentation terminée == activités finies #Droidcon #Robotium #Espresso @Tom404_
  41. 41. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner onCreate de l'application finalisée avant le début des tests Instrumentation terminée == activités finies Monitoring des activités plus fiable #Droidcon #Robotium #Espresso @Tom404_
  42. 42. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner 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 #Droidcon #Robotium #Espresso @Tom404_
  43. 43. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  44. 44. Robotium vs Espresso : Get ready to rumble ! Initialisation #Droidcon #Robotium #Espresso @Tom404_
  45. 45. Robotium vs Espresso : Get ready to rumble ! Initialisation 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(); } } #Droidcon #Robotium #Espresso @Tom404_
  46. 46. Robotium vs Espresso : Get ready to rumble ! Initialisation 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(); } } #Droidcon #Robotium #Espresso @Tom404_
  47. 47. Expressivité
  48. 48. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  49. 49. Robotium vs Espresso : Get ready to rumble ! API overview Robotium #Droidcon #Robotium #Espresso @Tom404_
  50. 50. Robotium vs Espresso : Get ready to rumble ! API overview #Droidcon #Robotium #Espresso Solo Robotium @Tom404_
  51. 51. Robotium vs Espresso : Get ready to rumble ! API overview clickOnActionBarHome() clickOnButton(int index) searchText(String text) pressSoftKeyboardNextButton() clickOnImageButton(int index) scrollDownList(int index) clearEditText(int index) scrollDown() clickOnToggleButton(String text) pressMenuItem(int index) #Droidcon #Robotium #Espresso Solo getView(int viewId) drag(…) clickInList(int line, int index) goBack() setNavigationDrawer(int status) clickOnActionBarItem(int id) getButton(int index) scrollToBottom() searchEditText(String text) pressSoftKeyboardSearchButton() @Tom404_
  52. 52. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  53. 53. Robotium vs Espresso : Get ready to rumble ! Exemple #Droidcon #Robotium #Espresso @Tom404_
  54. 54. Robotium vs Espresso : Get ready to rumble ! Exemple // 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) #Droidcon #Robotium #Espresso @Tom404_
  55. 55. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  56. 56. Robotium vs Espresso : Get ready to rumble ! Hamcrest #Droidcon #Robotium #Espresso @Tom404_
  57. 57. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers #Droidcon #Robotium #Espresso @Tom404_
  58. 58. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers assertThat("Hello", equalTo("Hello")) #Droidcon #Robotium #Espresso @Tom404_
  59. 59. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers assertThat("Hello", equalTo("Hello")) ! // Sucre syntaxique assertThat(“Hello", is("Hello")) #Droidcon #Robotium #Espresso @Tom404_
  60. 60. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers assertThat("Hello", equalTo("Hello")) ! // Sucre syntaxique assertThat(“Hello", is("Hello")) ! // De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase #Droidcon #Robotium #Espresso @Tom404_
  61. 61. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers assertThat("Hello", equalTo("Hello")) ! // Sucre syntaxique assertThat(“Hello", is("Hello")) ! // De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase Possibilité de composition #Droidcon #Robotium #Espresso @Tom404_
  62. 62. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  63. 63. Robotium vs Espresso : Get ready to rumble ! Hamcrest custom matcher #Droidcon #Robotium #Espresso @Tom404_
  64. 64. Robotium vs Espresso : Get ready to rumble ! Hamcrest custom matcher 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(); } ! } #Droidcon #Robotium #Espresso @Tom404_
  65. 65. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  66. 66. Robotium vs Espresso : Get ready to rumble ! API overview Espresso #Droidcon #Robotium #Espresso @Tom404_
  67. 67. Robotium vs Espresso : Get ready to rumble ! API overview Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> #Droidcon #Robotium #Espresso @Tom404_
  68. 68. Robotium vs Espresso : Get ready to rumble ! API overview ViewMatchers Espresso Espresso withId()! onView(Matcher<View>)! onData(Matcher<Object> #Droidcon #Robotium #Espresso withText(text)! hasSibling(Matcher<View>) @Tom404_
  69. 69. Robotium vs Espresso : Get ready to rumble ! API overview ViewMatchers Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> #Droidcon #Robotium #Espresso withId()! withText(text)! hasSibling(Matcher<View>) ViewActions click()! typeText(text) @Tom404_
  70. 70. Robotium vs Espresso : Get ready to rumble ! API overview ViewMatchers Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> #Droidcon #Robotium #Espresso withId()! withText(text)! hasSibling(Matcher<View>) ViewActions click()! typeText(text) ViewAssertions doesNotExist()! matches(Matcher<View>) @Tom404_
  71. 71. Robotium vs Espresso : Get ready to rumble ! API overview ViewMatchers Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> ViewInteraction / DataInteraction perform(ViewAction)! check(ViewAssertion) #Droidcon #Robotium #Espresso withId()! withText(text)! hasSibling(Matcher<View>) ViewActions click()! typeText(text) ViewAssertions doesNotExist()! matches(Matcher<View>) @Tom404_
  72. 72. Robotium vs Espresso : Get ready to rumble ! API overview ViewMatchers Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> ViewInteraction / DataInteraction perform(ViewAction)! check(ViewAssertion) #Droidcon #Robotium #Espresso withId()! withText(text)! hasSibling(Matcher<View>) ViewActions click()! typeText(text) ViewAssertions doesNotExist()! matches(Matcher<View>) @Tom404_
  73. 73. Robotium vs Espresso : Get ready to rumble ! API overview ViewMatchers Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> ViewInteraction / DataInteraction perform(ViewAction)! check(ViewAssertion) #Droidcon #Robotium #Espresso withId()! withText(text)! hasSibling(Matcher<View>) ViewActions click()! typeText(text) ViewAssertions doesNotExist()! matches(Matcher<View>) @Tom404_
  74. 74. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  75. 75. Robotium vs Espresso : Get ready to rumble ! Exemple #Droidcon #Robotium #Espresso @Tom404_
  76. 76. Robotium vs Espresso : Get ready to rumble ! Exemple onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click()); #Droidcon #Robotium #Espresso @Tom404_
  77. 77. Robotium vs Espresso : Get ready to rumble ! Exemple 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()); #Droidcon #Robotium #Espresso @Tom404_
  78. 78. Robotium vs Espresso : Get ready to rumble ! Exemple 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()); #Droidcon #Robotium #Espresso @Tom404_
  79. 79. Robotium vs Espresso : Get ready to rumble ! Exemple 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()); Manque de restrictions = AmbiguousViewMatcherException #Droidcon #Robotium #Espresso @Tom404_
  80. 80. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  81. 81. Robotium vs Espresso : Get ready to rumble ! Listview #Droidcon #Robotium #Espresso @Tom404_
  82. 82. Robotium vs Espresso : Get ready to rumble ! Listview Robotium // 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); #Droidcon #Robotium #Espresso @Tom404_
  83. 83. Robotium vs Espresso : Get ready to rumble ! Listview 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()); #Droidcon #Robotium #Espresso @Tom404_
  84. 84. Robotium vs Espresso : Get ready to rumble ! Listview Espresso : cas plus complexe // Type renvoyé par la méthode getItem de l'adapteur public class Item { public String name; public String itemContent; } ! onData(allOf(is(instanceOf(Item.class)), hasProperty(“name", equalTo(“nameToFind")))) .perform(click()); #Droidcon #Robotium #Espresso @Tom404_
  85. 85. Robotium vs Espresso : Get ready to rumble ! Listview Espresso : custom matcher 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); } }; } onData(withItemName(equalTo("nameToFind"))).perform(click()); #Droidcon #Robotium #Espresso @Tom404_
  86. 86. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  87. 87. Robotium vs Espresso : Get ready to rumble ! Webview Robotium #Droidcon #Robotium #Espresso @Tom404_
  88. 88. Robotium vs Espresso : Get ready to rumble ! Webview Robotium Possibilité d’interagir avec les webviews •solo.getWebElements(by) •solo.clickOnWebElement(by) #Droidcon #Robotium #Espresso @Tom404_
  89. 89. Robotium vs Espresso : Get ready to rumble ! Webview 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) #Droidcon #Robotium #Espresso @Tom404_
  90. 90. Robotium vs Espresso : Get ready to rumble ! Webview Espresso #Droidcon #Robotium #Espresso @Tom404_
  91. 91. Robotium vs Espresso : Get ready to rumble ! Webview Espresso #Droidcon #Robotium #Espresso @Tom404_
  92. 92. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  93. 93. Robotium vs Espresso : Get ready to rumble ! Navigation Drawer #Droidcon #Robotium #Espresso @Tom404_
  94. 94. Robotium vs Espresso : Get ready to rumble ! Navigation Drawer Robotium // Attention l'id du frame layout du menu doit absolument être "left_drawer" solo.setNavigationDrawer(Solo.OPENED); ! solo.setNavigationDrawer(Solo.CLOSED); #Droidcon #Robotium #Espresso @Tom404_
  95. 95. Robotium vs Espresso : Get ready to rumble ! Navigation Drawer 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); #Droidcon #Robotium #Espresso @Tom404_
  96. 96. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  97. 97. Robotium vs Espresso : Get ready to rumble ! Action bar #Droidcon #Robotium #Espresso @Tom404_
  98. 98. Robotium vs Espresso : Get ready to rumble ! Action bar Robotium solo.clickOnActionBarItem(R.id.action_example); ! // Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action"); #Droidcon #Robotium #Espresso @Tom404_
  99. 99. Robotium vs Espresso : Get ready to rumble ! Action bar 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()); #Droidcon #Robotium #Espresso @Tom404_
  100. 100. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  101. 101. Robotium vs Espresso : Get ready to rumble ! Back button & Keyboard #Droidcon #Robotium #Espresso @Tom404_
  102. 102. Robotium vs Espresso : Get ready to rumble ! Back button & Keyboard Robotium solo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier #Droidcon #Robotium #Espresso @Tom404_
  103. 103. Robotium vs Espresso : Get ready to rumble ! Back button & Keyboard Robotium solo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier Espresso Espresso.pressBack(); Espresso.closeSoftKeyboard(); #Droidcon #Robotium #Espresso @Tom404_
  104. 104. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  105. 105. Robotium vs Espresso : Get ready to rumble ! Les messages d’erreur #Droidcon #Robotium #Espresso @Tom404_
  106. 106. Robotium vs Espresso : Get ready to rumble ! Les messages d’erreur Robotium ! // Récupération d’une vue inexistante solo.getView(1234); !j unit.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) #Droidcon #Robotium #Espresso @Tom404_
  107. 107. Robotium vs Espresso : Get ready to rumble ! Les messages d’erreur Espresso ! // Récupération d’une vue inexistante onView(withId(1234)); 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, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is- #Droidcon #Robotium #Espresso @Tom404_
  108. 108. Enchaînements
  109. 109. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  110. 110. Robotium vs Espresso : Get ready to rumble ! Wait and See #Droidcon #Robotium #Espresso @Tom404_
  111. 111. Robotium vs Espresso : Get ready to rumble ! Wait and See Robotium repose sur le principe de wait & see •solo.waitForActivity(Class class, int timeout) • solo.waitForCondition(Condition condition, int timeout) • solo.waitForDialogToOpen() #Droidcon #Robotium #Espresso @Tom404_
  112. 112. Robotium vs Espresso : Get ready to rumble ! Wait and See Robotium repose sur le principe de wait & see •solo.waitForActivity(Class class, int timeout) • solo.waitForCondition(Condition condition, int timeout) • solo.waitForDialogToOpen() 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); #Droidcon #Robotium #Espresso @Tom404_
  113. 113. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  114. 114. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! #Droidcon #Robotium #Espresso @Tom404_
  115. 115. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! Entrée en jeu du GoogleInstrumentationTestRunner #Droidcon #Robotium #Espresso @Tom404_
  116. 116. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! Entrée en jeu du GoogleInstrumentationTestRunner Monitoring plus fin des activités et des ressources #Droidcon #Robotium #Espresso @Tom404_
  117. 117. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! Entrée en jeu du GoogleInstrumentationTestRunner Monitoring plus fin des activités et des ressources Analyse du ThreadUI pour savoir quand agir #Droidcon #Robotium #Espresso @Tom404_
  118. 118. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! 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 #Droidcon #Robotium #Espresso @Tom404_
  119. 119. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! 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 onView(withId(R.id.start_activity_button)).perform(click()); ! onView(withId(R.id.view_in_new_activity)).perform(click()); #Droidcon #Robotium #Espresso @Tom404_
  120. 120. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  121. 121. Robotium vs Espresso : Get ready to rumble ! Idle mais actif ! #Droidcon #Robotium #Espresso @Tom404_
  122. 122. Robotium vs Espresso : Get ready to rumble ! Idle mais actif ! Possibilité d'enregistrer des idlingResources #Droidcon #Robotium #Espresso @Tom404_
  123. 123. Robotium vs Espresso : Get ready to rumble ! 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(); } } } #Droidcon #Robotium #Espresso @Tom404_
  124. 124. Robotium vs Espresso : Get ready to rumble ! 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); #Droidcon #Robotium #Espresso @Tom404_
  125. 125. Conclusion
  126. 126. Questions ?

×