SlideShare a Scribd company logo
DroidCon 2014 - Robotium vs espresso_droidcon
DroidCon 2014 - Robotium vs espresso_droidcon
Robotiumvs Espresso 
Get ready to rumble !
DroidCon 2014 - Robotium vs espresso_droidcon
Thomas Guerin
Thomas Guerin 
Développeur Android
Thomas Guerin 
Développeur Android 
Tests addict
Thomas Guerin 
Développeur Android 
Tests addict 
Niveau 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 !” 
“Tester ce n’est pas toujours simple !” 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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… 
Simple 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Un test doit être… 
Simple Rapide 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Un test doit être… 
Simple Rapide Fiable 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Un test doit être… 
Simple Rapide Fiable Durable 
#Droidcon #Robotium #Espresso 
@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 
// 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_
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_
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 
Robotium 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Les combattants 
#Droidcon #Robotium #Espresso 
VS 
Robotium Espresso 
@Tom404_
DroidCon 2014 - Robotium vs espresso_droidcon
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 
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_
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_
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_
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 
Robotium utilise le test runner du sdk 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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 
onCreate de l'application finalisée avant le début des tests 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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_
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 
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_
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_
DroidCon 2014 - Robotium vs espresso_droidcon
Expressivité
Robotium vs Espresso : Get ready to rumble ! 
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble ! 
API overview 
Robotium 
#Droidcon #Robotium #Espresso 
@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 
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_
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 
// 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_
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 
Librairie de matchers 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Hamcrest 
Librairie de matchers 
assertThat("Hello", equalTo("Hello")) 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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_
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 
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_
Robotium vs Espresso : Get ready to rumble ! 
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble ! 
API overview 
Espresso 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
API overview 
Espresso 
Espresso 
onView(Matcher<View>)! 
onData(Matcher<Object> 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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_
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_
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_
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_
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 
onView(allOf(withId(R.id.my_button), withText(“My Button”))) 
.check(matches(isDisplayed())) 
.perform(click()); 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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_
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 
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_
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_
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_
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_
Robotium vs Espresso : Get ready to rumble ! 
#Droidcon #Robotium #Espresso @Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Webview 
Robotium 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
Robotium vs Espresso : Get ready to rumble ! 
Webview 
Espresso 
#Droidcon #Robotium #Espresso 
@Tom404_
Robotium vs Espresso : Get ready to rumble ! 
Webview 
Espresso 
#Droidcon #Robotium #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 
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_
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_
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 
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_
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_
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 
Robotium 
solo.goBack(); 
// solo.goBack() est aussi utilisé pour fermer le clavier 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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 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_
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_
DroidCon 2014 - Robotium vs espresso_droidcon
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 
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_
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_
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 ! 
Entrée en jeu du GoogleInstrumentationTestRunner 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
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_
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_
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 ! 
Possibilité d'enregistrer des idlingResources 
#Droidcon #Robotium #Espresso 
@Tom404_
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_
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_
DroidCon 2014 - Robotium vs espresso_droidcon
Conclusion
DroidCon 2014 - Robotium vs espresso_droidcon
Questions ?
DroidCon 2014 - Robotium vs espresso_droidcon

More Related Content

PDF
What is mt-chamber?
PDF
Présentations Café des Possibles ShaREvolution en Seine-Saint-Denis à Bobigny
PPT
Pobreza I ExclusióN I GlobalizacióN
PPT
Glosario Digital
PPT
Sistema Operativo Linuxinfo
PPS
CAPACITACION NUEVOS MIEMBROS MONA-VIE
PPTX
Advanced Negatives
PDF
Expérimentation Infolab au sein du réseau Information-Jeunesse de la région P...
What is mt-chamber?
Présentations Café des Possibles ShaREvolution en Seine-Saint-Denis à Bobigny
Pobreza I ExclusióN I GlobalizacióN
Glosario Digital
Sistema Operativo Linuxinfo
CAPACITACION NUEVOS MIEMBROS MONA-VIE
Advanced Negatives
Expérimentation Infolab au sein du réseau Information-Jeunesse de la région P...

Viewers also liked (20)

PDF
PACA Lights by PACA Labs - 8 décembre 2014, Marseille, La Boate
PDF
Prez infolab-bilan2015
PPT
Power Point2003
PPT
como subir presentaciones a slideshare.
PDF
Scrum day 2013 sponsoring package
DOC
T, suzanne valadon et ses souvenirs de modèle
PDF
tariq-cert
PPT
Presentacion Da Tectonica De Placas
PDF
memoguide_CHASSEZAC
PPS
Belllissima nature s-best_photography
PPS
9 suggestions de cadeaux
PDF
Remess actes de_la_rencontre_africaine_kenitra_2010
ODP
Curso de primeros auxilios CPR de Mérida
PDF
Tenant Improvement - Alert Logic
PDF
Presentation Way To Blue Fr
PPT
PDF
definiciones preliminares2007
PDF
Manejo básico netvibes
PDF
GreenIvory : produits & services
PACA Lights by PACA Labs - 8 décembre 2014, Marseille, La Boate
Prez infolab-bilan2015
Power Point2003
como subir presentaciones a slideshare.
Scrum day 2013 sponsoring package
T, suzanne valadon et ses souvenirs de modèle
tariq-cert
Presentacion Da Tectonica De Placas
memoguide_CHASSEZAC
Belllissima nature s-best_photography
9 suggestions de cadeaux
Remess actes de_la_rencontre_africaine_kenitra_2010
Curso de primeros auxilios CPR de Mérida
Tenant Improvement - Alert Logic
Presentation Way To Blue Fr
definiciones preliminares2007
Manejo básico netvibes
GreenIvory : produits & services
Ad

Similar to DroidCon 2014 - Robotium vs espresso_droidcon (8)

PPTX
Testing android apps with espresso
PDF
Espresso devoxx 2014
PDF
Przyszłość ma na imię Mobile – testowanie i automatyzacja testów aplikacji mo...
PPTX
Espresso workshop
PDF
Robotium - sampath
PDF
Rockstar Android Testing (Mobile TechCon Munich 2014)
PDF
Introduction to Robotium
PPTX
Do You Enjoy Espresso in Android App Testing?
Testing android apps with espresso
Espresso devoxx 2014
Przyszłość ma na imię Mobile – testowanie i automatyzacja testów aplikacji mo...
Espresso workshop
Robotium - sampath
Rockstar Android Testing (Mobile TechCon Munich 2014)
Introduction to Robotium
Do You Enjoy Espresso in Android App Testing?
Ad

More from Publicis Sapient Engineering (20)

PDF
XebiCon'18 - L'algorithme de reconnaissance de formes par le cerveau humain
PDF
Xebicon'18 - IoT: From Edge to Cloud
PDF
Xebicon'18 - Spark in jail : conteneurisez vos traitements data sans serveur
PDF
XebiCon'18 - Modern Infrastructure
PDF
XebiCon'18 - La Web App d'aujourd'hui et de demain : état de l'art et bleedin...
PDF
XebiCon'18 - Des notebook pour le monitoring avec Zeppelin
PDF
XebiCon'18 - Event Sourcing et RGPD, incompatibles ?
PDF
XebiCon'18 - Deno, le nouveau NodeJS qui inverse la tendance ?
PDF
XebiCon'18 - Boostez vos modèles avec du Deep Learning distribué
PDF
XebiCon'18 - Comment j'ai développé un jeu vidéo avec des outils de développe...
PDF
XebiCon'18 - Les utilisateurs finaux, les oubliés de nos produits !
PDF
XebiCon'18 - Comment fausser l'interprétation de vos résultats avec des dataviz
PDF
XebiCon'18 - Le développeur dans la Pop Culture
PDF
XebiCon'18 - Architecturer son application mobile pour la durabilité
PDF
XebiCon'18 - Sécuriser son API avec OpenID Connect
PDF
XebiCon'18 - Structuration du Temps et Dynamique de Groupes, Théorie organisa...
PDF
XebiCon'18 - Spark NLP, un an après
PDF
XebiCon'18 - La sécurité, douce illusion même en 2018
PDF
XebiCon'18 - Utiliser Hyperledger Fabric pour la création d'une blockchain pr...
PDF
XebiCon'18 - Ce que l'histoire du métro Parisien m'a enseigné sur la création...
XebiCon'18 - L'algorithme de reconnaissance de formes par le cerveau humain
Xebicon'18 - IoT: From Edge to Cloud
Xebicon'18 - Spark in jail : conteneurisez vos traitements data sans serveur
XebiCon'18 - Modern Infrastructure
XebiCon'18 - La Web App d'aujourd'hui et de demain : état de l'art et bleedin...
XebiCon'18 - Des notebook pour le monitoring avec Zeppelin
XebiCon'18 - Event Sourcing et RGPD, incompatibles ?
XebiCon'18 - Deno, le nouveau NodeJS qui inverse la tendance ?
XebiCon'18 - Boostez vos modèles avec du Deep Learning distribué
XebiCon'18 - Comment j'ai développé un jeu vidéo avec des outils de développe...
XebiCon'18 - Les utilisateurs finaux, les oubliés de nos produits !
XebiCon'18 - Comment fausser l'interprétation de vos résultats avec des dataviz
XebiCon'18 - Le développeur dans la Pop Culture
XebiCon'18 - Architecturer son application mobile pour la durabilité
XebiCon'18 - Sécuriser son API avec OpenID Connect
XebiCon'18 - Structuration du Temps et Dynamique de Groupes, Théorie organisa...
XebiCon'18 - Spark NLP, un an après
XebiCon'18 - La sécurité, douce illusion même en 2018
XebiCon'18 - Utiliser Hyperledger Fabric pour la création d'une blockchain pr...
XebiCon'18 - Ce que l'histoire du métro Parisien m'a enseigné sur la création...

Recently uploaded (20)

PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
Machine Learning_overview_presentation.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Electronic commerce courselecture one. Pdf
PDF
Approach and Philosophy of On baking technology
PDF
Machine learning based COVID-19 study performance prediction
PPTX
Cloud computing and distributed systems.
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Empathic Computing: Creating Shared Understanding
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
sap open course for s4hana steps from ECC to s4
Reach Out and Touch Someone: Haptics and Empathic Computing
NewMind AI Weekly Chronicles - August'25-Week II
Machine Learning_overview_presentation.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Programs and apps: productivity, graphics, security and other tools
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Electronic commerce courselecture one. Pdf
Approach and Philosophy of On baking technology
Machine learning based COVID-19 study performance prediction
Cloud computing and distributed systems.
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Spectral efficient network and resource selection model in 5G networks
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Empathic Computing: Creating Shared Understanding

DroidCon 2014 - Robotium vs espresso_droidcon

  • 3. Robotiumvs Espresso Get ready to rumble !
  • 7. Thomas Guerin Développeur Android Tests addict
  • 8. Thomas Guerin Développeur Android Tests addict Niveau 15 à Destiny
  • 9. Robotium vs Espresso : Get ready to rumble !
  • 10. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? #Droidcon #Robotium #Espresso @Tom404_
  • 11. Robotium vs Espresso : Get ready to rumble ! Pourquoi ne pas faire de tests ? “Mes tests durent des heures !” #Droidcon #Robotium #Espresso @Tom404_
  • 12. 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_
  • 13. 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_
  • 14. 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_
  • 15. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 16. Robotium vs Espresso : Get ready to rumble ! Un test doit être… #Droidcon #Robotium #Espresso @Tom404_
  • 17. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple #Droidcon #Robotium #Espresso @Tom404_
  • 18. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple Rapide #Droidcon #Robotium #Espresso @Tom404_
  • 19. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple Rapide Fiable #Droidcon #Robotium #Espresso @Tom404_
  • 20. Robotium vs Espresso : Get ready to rumble ! Un test doit être… Simple Rapide Fiable Durable #Droidcon #Robotium #Espresso @Tom404_
  • 21. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 22. Robotium vs Espresso : Get ready to rumble ! Un mauvais exemple #Droidcon #Robotium #Espresso @Tom404_
  • 23. 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_
  • 24. 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_
  • 25. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 26. Robotium vs Espresso : Get ready to rumble ! Les combattants #Droidcon #Robotium #Espresso @Tom404_
  • 27. Robotium vs Espresso : Get ready to rumble ! Les combattants Robotium #Droidcon #Robotium #Espresso @Tom404_
  • 28. Robotium vs Espresso : Get ready to rumble ! Les combattants #Droidcon #Robotium #Espresso VS Robotium Espresso @Tom404_
  • 31. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 32. Robotium vs Espresso : Get ready to rumble ! Dépendances Gradle #Droidcon #Robotium #Espresso @Tom404_
  • 33. 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_
  • 34. 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_
  • 35. 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_
  • 36. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 37. Robotium vs Espresso : Get ready to rumble ! Test Runner #Droidcon #Robotium #Espresso @Tom404_
  • 38. Robotium vs Espresso : Get ready to rumble ! Test Runner Robotium utilise le test runner du sdk #Droidcon #Robotium #Espresso @Tom404_
  • 39. 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_
  • 40. 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_
  • 41. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 42. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner #Droidcon #Robotium #Espresso @Tom404_
  • 43. Robotium vs Espresso : Get ready to rumble ! GoogleInstrumentationTestRunner onCreate de l'application finalisée avant le début des tests #Droidcon #Robotium #Espresso @Tom404_
  • 44. 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_
  • 45. 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_
  • 46. 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_
  • 47. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 48. Robotium vs Espresso : Get ready to rumble ! Initialisation #Droidcon #Robotium #Espresso @Tom404_
  • 49. 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_
  • 50. 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_
  • 53. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 54. Robotium vs Espresso : Get ready to rumble ! API overview Robotium #Droidcon #Robotium #Espresso @Tom404_
  • 55. Robotium vs Espresso : Get ready to rumble ! API overview #Droidcon #Robotium #Espresso Solo Robotium @Tom404_
  • 56. 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_
  • 57. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 58. Robotium vs Espresso : Get ready to rumble ! Exemple #Droidcon #Robotium #Espresso @Tom404_
  • 59. 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_
  • 60. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 61. Robotium vs Espresso : Get ready to rumble ! Hamcrest #Droidcon #Robotium #Espresso @Tom404_
  • 62. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers #Droidcon #Robotium #Espresso @Tom404_
  • 63. Robotium vs Espresso : Get ready to rumble ! Hamcrest Librairie de matchers assertThat("Hello", equalTo("Hello")) #Droidcon #Robotium #Espresso @Tom404_
  • 64. 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_
  • 65. 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_
  • 66. 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_
  • 67. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 68. Robotium vs Espresso : Get ready to rumble ! Hamcrest custom matcher #Droidcon #Robotium #Espresso @Tom404_
  • 69. 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_
  • 70. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 71. Robotium vs Espresso : Get ready to rumble ! API overview Espresso #Droidcon #Robotium #Espresso @Tom404_
  • 72. Robotium vs Espresso : Get ready to rumble ! API overview Espresso Espresso onView(Matcher<View>)! onData(Matcher<Object> #Droidcon #Robotium #Espresso @Tom404_
  • 73. 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_
  • 74. 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_
  • 75. 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_
  • 76. 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_
  • 77. 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_
  • 78. 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_
  • 79. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 80. Robotium vs Espresso : Get ready to rumble ! Exemple #Droidcon #Robotium #Espresso @Tom404_
  • 81. 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_
  • 82. 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_
  • 83. 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_
  • 84. 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_
  • 85. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 86. Robotium vs Espresso : Get ready to rumble ! Listview #Droidcon #Robotium #Espresso @Tom404_
  • 87. 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_
  • 88. 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_
  • 89. 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_
  • 90. 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_
  • 91. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 92. Robotium vs Espresso : Get ready to rumble ! Webview Robotium #Droidcon #Robotium #Espresso @Tom404_
  • 93. 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_
  • 94. 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_
  • 95. Robotium vs Espresso : Get ready to rumble ! Webview Espresso #Droidcon #Robotium #Espresso @Tom404_
  • 96. Robotium vs Espresso : Get ready to rumble ! Webview Espresso #Droidcon #Robotium #Espresso @Tom404_
  • 97. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 98. Robotium vs Espresso : Get ready to rumble ! Navigation Drawer #Droidcon #Robotium #Espresso @Tom404_
  • 99. 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_
  • 100. 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_
  • 101. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 102. Robotium vs Espresso : Get ready to rumble ! Action bar #Droidcon #Robotium #Espresso @Tom404_
  • 103. 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_
  • 104. 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_
  • 105. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 106. Robotium vs Espresso : Get ready to rumble ! Back button & Keyboard #Droidcon #Robotium #Espresso @Tom404_
  • 107. 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_
  • 108. 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_
  • 109. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 110. Robotium vs Espresso : Get ready to rumble ! Les messages d’erreur #Droidcon #Robotium #Espresso @Tom404_
  • 111. 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_
  • 112. 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_
  • 115. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 116. Robotium vs Espresso : Get ready to rumble ! Wait and See #Droidcon #Robotium #Espresso @Tom404_
  • 117. 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_
  • 118. 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_
  • 119. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 120. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! #Droidcon #Robotium #Espresso @Tom404_
  • 121. Robotium vs Espresso : Get ready to rumble ! Finis de dormir ! Entrée en jeu du GoogleInstrumentationTestRunner #Droidcon #Robotium #Espresso @Tom404_
  • 122. 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_
  • 123. 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_
  • 124. 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_
  • 125. 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_
  • 126. Robotium vs Espresso : Get ready to rumble ! #Droidcon #Robotium #Espresso @Tom404_
  • 127. Robotium vs Espresso : Get ready to rumble ! Idle mais actif ! #Droidcon #Robotium #Espresso @Tom404_
  • 128. Robotium vs Espresso : Get ready to rumble ! Idle mais actif ! Possibilité d'enregistrer des idlingResources #Droidcon #Robotium #Espresso @Tom404_
  • 129. 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_
  • 130. 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_