Post on 05-Dec-2014
description
Robotium vs EspressoGet ready to rumble !
Thomas Guerin
Thomas GuerinDéveloppeur Android
Thomas GuerinDéveloppeur Android
Tests addict
Thomas GuerinDéveloppeur Android
Tests addictNiveau 15 à Destiny
Robotium vs Espresso : Get ready to rumble !
Robotium vs Espresso : Get ready to rumble !
Pourquoi ne pas faire de tests ?
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Pourquoi ne pas faire de tests ?
“Mes tests durent des heures !”
#Droidcon #Robotium #Espresso @Tom404_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Un test doit être…
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Un test doit être…
#Droidcon #Robotium #Espresso
Simple
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Un test doit être…
#Droidcon #Robotium #Espresso
RapideSimple
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Un test doit être…
#Droidcon #Robotium #Espresso
RapideSimple Fiable
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Un test doit être…
#Droidcon #Robotium #Espresso
RapideSimple Fiable Durable
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Un mauvais exemple
#Droidcon #Robotium #Espresso @Tom404_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Les combattants
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Les combattants
#Droidcon #Robotium #Espresso
Robotium
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Les combattants
#Droidcon #Robotium #Espresso
VS
Robotium Espresso
@Tom404_
Préparation
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Dépendances Gradle
#Droidcon #Robotium #Espresso @Tom404_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Test Runner
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Test Runner
#Droidcon #Robotium #Espresso
Robotium utilise le test runner du sdk
@Tom404_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
GoogleInstrumentationTestRunner
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
GoogleInstrumentationTestRunner
#Droidcon #Robotium #Espresso
onCreate de l'application finalisée avant le début des tests
@Tom404_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Initialisation
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Initialisation
#Droidcon #Robotium #Espresso
Robotiumpublic 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_
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_
Expressivité
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
API overview
#Droidcon #Robotium #Espresso
Robotium
@Tom404_
Robotium vs Espresso : Get ready to rumble !
API overview
#Droidcon #Robotium #Espresso
Solo
Robotium
@Tom404_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Exemple
#Droidcon #Robotium #Espresso @Tom404_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest
#Droidcon #Robotium #Espresso
Librairie de matchers
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest
#Droidcon #Robotium #Espresso
Librairie de matchersassertThat("Hello", equalTo("Hello"))
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest
#Droidcon #Robotium #Espresso
Librairie de matchersassertThat("Hello", equalTo("Hello"))!// Sucre syntaxique assertThat(“Hello", is("Hello"))
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest
#Droidcon #Robotium #Espresso
Librairie de matchersassertThat("Hello", equalTo("Hello"))!// Sucre syntaxique assertThat(“Hello", is("Hello"))!// De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest
#Droidcon #Robotium #Espresso
Librairie de matchersassertThat("Hello", equalTo("Hello"))!// Sucre syntaxique assertThat(“Hello", is("Hello"))
Possibilité de composition
!// De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Hamcrest custom matcher
#Droidcon #Robotium #Espresso @Tom404_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
API overview
#Droidcon #Robotium #Espresso
Espresso
@Tom404_
Robotium vs Espresso : Get ready to rumble !
API overview
#Droidcon #Robotium #Espresso
onView(Matcher<View>)!onData(Matcher<Object>
Espresso
Espresso
@Tom404_
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>)
ViewMatchersEspresso
@Tom404_
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>)
ViewMatchersEspresso
@Tom404_
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>)
ViewMatchersEspresso
@Tom404_
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>)
ViewMatchersEspresso
@Tom404_
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>)
ViewMatchersEspresso
@Tom404_
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>)
ViewMatchersEspresso
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Exemple
#Droidcon #Robotium #Espresso @Tom404_
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_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Listview
#Droidcon #Robotium #Espresso @Tom404_
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_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Webview
#Droidcon #Robotium #Espresso
Robotium
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Webview
#Droidcon #Robotium #Espresso
RobotiumPossibilité d’interagir avec les webviews
•solo.getWebElements(by)•solo.clickOnWebElement(by)
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Webview
#Droidcon #Robotium #Espresso
RobotiumPossibilité 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_
Robotium vs Espresso : Get ready to rumble !
Webview
#Droidcon #Robotium #Espresso
Espresso
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Webview
#Droidcon #Robotium #Espresso
Espresso
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Navigation Drawer
#Droidcon #Robotium #Espresso @Tom404_
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_
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);
EspressoDrawerActions.openDrawer(R.id.drawer_layout); !DrawerActions.closeDrawer(R.id.drawer_layout);
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Action bar
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Action bar
#Droidcon #Robotium #Espresso
Robotiumsolo.clickOnActionBarItem(R.id.action_example); !// Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action");
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Action bar
#Droidcon #Robotium #Espresso
Robotiumsolo.clickOnActionBarItem(R.id.action_example); !// Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action");
EspressoonView(withId(R.id_action_example)).perform(click()); !// Cas de l'action bar overflow openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); onView(withText("action")).perform(click());
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Back button & Keyboard
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Back button & Keyboard
#Droidcon #Robotium #Espresso
Robotiumsolo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier
@Tom404_
Robotium vs Espresso : Get ready to rumble !
Back button & Keyboard
#Droidcon #Robotium #Espresso
Robotiumsolo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier
EspressoEspresso.pressBack(); Espresso.closeSoftKeyboard();
@Tom404_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Les messages d’erreur
#Droidcon #Robotium #Espresso @Tom404_
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(SimpleActionsTest.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_
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-
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_
Enchaînements
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Wait and See
#Droidcon #Robotium #Espresso @Tom404_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Finis de dormir !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Finis de dormir !
#Droidcon #Robotium #Espresso
Entrée en jeu du GoogleInstrumentationTestRunner
@Tom404_
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_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Idle mais actif !
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble !
Idle mais actif !
#Droidcon #Robotium #Espresso
Possibilité d'enregistrer des idlingResources
@Tom404_
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_
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_
Conclusion
Questions ?