SlideShare une entreprise Scribd logo
1  sur  135
Télécharger pour lire hors ligne
Robotiumvs Espresso 
Get ready to rumble !
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_
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_
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_
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_
Conclusion
Questions ?
Robotium vs Espresso: Get ready to rumble ! - DroidCon Paris 2014

Contenu connexe

Similaire à Robotium vs Espresso: Get ready to rumble ! - DroidCon Paris 2014

Testing with Docker
Testing with DockerTesting with Docker
Testing with Dockertoffermann
 
Hotfixing iOS apps with Javascript
Hotfixing iOS apps with JavascriptHotfixing iOS apps with Javascript
Hotfixing iOS apps with JavascriptSergio Padrino Recio
 
The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...
The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...
The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...Hinling Yeung
 
Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)Anna Schneider
 
Practical unit testing 2014
Practical unit testing 2014Practical unit testing 2014
Practical unit testing 2014Andrew Fray
 
Mobile Development integration tests
Mobile Development integration testsMobile Development integration tests
Mobile Development integration testsKenneth Poon
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMockYing Zhang
 
Monkeybars in the Manor
Monkeybars in the ManorMonkeybars in the Manor
Monkeybars in the Manormartinbtt
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introductionNir Kaufman
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...Yevgeniy Brikman
 
Aprendendo solid com exemplos
Aprendendo solid com exemplosAprendendo solid com exemplos
Aprendendo solid com exemplosvinibaggio
 
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovygreach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovyJessie Evangelista
 
I just hacked your app! - Marcos Placona - Codemotion Rome 2017
I just hacked your app! - Marcos Placona - Codemotion Rome 2017I just hacked your app! - Marcos Placona - Codemotion Rome 2017
I just hacked your app! - Marcos Placona - Codemotion Rome 2017Codemotion
 
Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014
Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014
Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014Ricardo Dorta
 
Design and Evolution of cyber-dojo
Design and Evolution of cyber-dojoDesign and Evolution of cyber-dojo
Design and Evolution of cyber-dojoJon Jagger
 
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...jeromevdl
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahNick Plante
 
Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...
Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...
Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...Puppet
 

Similaire à Robotium vs Espresso: Get ready to rumble ! - DroidCon Paris 2014 (20)

Testing with Docker
Testing with DockerTesting with Docker
Testing with Docker
 
Hotfixing iOS apps with Javascript
Hotfixing iOS apps with JavascriptHotfixing iOS apps with Javascript
Hotfixing iOS apps with Javascript
 
The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...
The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...
The Chronicle of iPhone Automation -- From Frank to UISpec to UIAutomation to...
 
Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)
 
Practical unit testing 2014
Practical unit testing 2014Practical unit testing 2014
Practical unit testing 2014
 
Mobile Development integration tests
Mobile Development integration testsMobile Development integration tests
Mobile Development integration tests
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
 
Monkeybars in the Manor
Monkeybars in the ManorMonkeybars in the Manor
Monkeybars in the Manor
 
Testing smells
Testing smellsTesting smells
Testing smells
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
 
Deviceanywhere studio 5.1
Deviceanywhere studio 5.1Deviceanywhere studio 5.1
Deviceanywhere studio 5.1
 
Aprendendo solid com exemplos
Aprendendo solid com exemplosAprendendo solid com exemplos
Aprendendo solid com exemplos
 
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovygreach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
 
I just hacked your app! - Marcos Placona - Codemotion Rome 2017
I just hacked your app! - Marcos Placona - Codemotion Rome 2017I just hacked your app! - Marcos Placona - Codemotion Rome 2017
I just hacked your app! - Marcos Placona - Codemotion Rome 2017
 
Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014
Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014
Ciclo de Vida de Aplicativos Windows - The Developers Conferece 2014
 
Design and Evolution of cyber-dojo
Design and Evolution of cyber-dojoDesign and Evolution of cyber-dojo
Design and Evolution of cyber-dojo
 
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
 
Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...
Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...
Puppet Camp Düsseldorf 2014: Continuously Deliver Your Puppet Code with Jenki...
 

Plus de Paris Android User Group

Workshop: building your mobile backend with Parse - Droidcon Paris2014
Workshop: building your mobile backend with Parse - Droidcon Paris2014Workshop: building your mobile backend with Parse - Droidcon Paris2014
Workshop: building your mobile backend with Parse - Droidcon Paris2014Paris Android User Group
 
Workshop: Amazon developer ecosystem - DroidCon Paris2014
Workshop: Amazon developer ecosystem - DroidCon Paris2014Workshop: Amazon developer ecosystem - DroidCon Paris2014
Workshop: Amazon developer ecosystem - DroidCon Paris2014Paris Android User Group
 
Extending your apps to wearables - DroidCon Paris 2014
Extending your apps to wearables -  DroidCon Paris 2014Extending your apps to wearables -  DroidCon Paris 2014
Extending your apps to wearables - DroidCon Paris 2014Paris Android User Group
 
Scaling android development - DroidCon Paris 2014
Scaling android development - DroidCon Paris 2014Scaling android development - DroidCon Paris 2014
Scaling android development - DroidCon Paris 2014Paris Android User Group
 
Ingredient of awesome app - DroidCon Paris 2014
Ingredient of awesome app - DroidCon Paris 2014Ingredient of awesome app - DroidCon Paris 2014
Ingredient of awesome app - DroidCon Paris 2014Paris Android User Group
 
Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014Paris Android User Group
 
Archos Android based connected home solution - DroidCon Paris 2014
Archos Android based connected home solution - DroidCon Paris 2014Archos Android based connected home solution - DroidCon Paris 2014
Archos Android based connected home solution - DroidCon Paris 2014Paris Android User Group
 
Porting VLC on Android - DroidCon Paris 2014
Porting VLC on Android - DroidCon Paris 2014Porting VLC on Android - DroidCon Paris 2014
Porting VLC on Android - DroidCon Paris 2014Paris Android User Group
 
maximize app engagement and monetization - DroidCon Paris 2014
maximize app engagement and monetization - DroidCon Paris 2014maximize app engagement and monetization - DroidCon Paris 2014
maximize app engagement and monetization - DroidCon Paris 2014Paris Android User Group
 
Using the android ndk - DroidCon Paris 2014
Using the android ndk - DroidCon Paris 2014Using the android ndk - DroidCon Paris 2014
Using the android ndk - DroidCon Paris 2014Paris Android User Group
 
Holo material design transition - DroidCon Paris 2014
Holo material design transition - DroidCon Paris 2014Holo material design transition - DroidCon Paris 2014
Holo material design transition - DroidCon Paris 2014Paris Android User Group
 
Google glass droidcon - DroidCon Paris 2014
Google glass droidcon - DroidCon Paris 2014Google glass droidcon - DroidCon Paris 2014
Google glass droidcon - DroidCon Paris 2014Paris Android User Group
 
Embedded webserver implementation and usage - DroidCon Paris 2014
Embedded webserver implementation and usage - DroidCon Paris 2014Embedded webserver implementation and usage - DroidCon Paris 2014
Embedded webserver implementation and usage - DroidCon Paris 2014Paris Android User Group
 
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014Paris Android User Group
 
What's new in android 4.4 - Romain Guy & Chet Haase
What's new in android 4.4 - Romain Guy & Chet HaaseWhat's new in android 4.4 - Romain Guy & Chet Haase
What's new in android 4.4 - Romain Guy & Chet HaaseParis Android User Group
 
Efficient Image Processing - Nicolas Roard
Efficient Image Processing - Nicolas RoardEfficient Image Processing - Nicolas Roard
Efficient Image Processing - Nicolas RoardParis Android User Group
 

Plus de Paris Android User Group (20)

Workshop: building your mobile backend with Parse - Droidcon Paris2014
Workshop: building your mobile backend with Parse - Droidcon Paris2014Workshop: building your mobile backend with Parse - Droidcon Paris2014
Workshop: building your mobile backend with Parse - Droidcon Paris2014
 
Workshop: Amazon developer ecosystem - DroidCon Paris2014
Workshop: Amazon developer ecosystem - DroidCon Paris2014Workshop: Amazon developer ecosystem - DroidCon Paris2014
Workshop: Amazon developer ecosystem - DroidCon Paris2014
 
Extending your apps to wearables - DroidCon Paris 2014
Extending your apps to wearables -  DroidCon Paris 2014Extending your apps to wearables -  DroidCon Paris 2014
Extending your apps to wearables - DroidCon Paris 2014
 
Scaling android development - DroidCon Paris 2014
Scaling android development - DroidCon Paris 2014Scaling android development - DroidCon Paris 2014
Scaling android development - DroidCon Paris 2014
 
Ingredient of awesome app - DroidCon Paris 2014
Ingredient of awesome app - DroidCon Paris 2014Ingredient of awesome app - DroidCon Paris 2014
Ingredient of awesome app - DroidCon Paris 2014
 
Framing the canvas - DroidCon Paris 2014
Framing the canvas - DroidCon Paris 2014Framing the canvas - DroidCon Paris 2014
Framing the canvas - DroidCon Paris 2014
 
Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014
 
Archos Android based connected home solution - DroidCon Paris 2014
Archos Android based connected home solution - DroidCon Paris 2014Archos Android based connected home solution - DroidCon Paris 2014
Archos Android based connected home solution - DroidCon Paris 2014
 
Porting VLC on Android - DroidCon Paris 2014
Porting VLC on Android - DroidCon Paris 2014Porting VLC on Android - DroidCon Paris 2014
Porting VLC on Android - DroidCon Paris 2014
 
Buildsystem.mk - DroidCon Paris 2014
Buildsystem.mk - DroidCon Paris 2014Buildsystem.mk - DroidCon Paris 2014
Buildsystem.mk - DroidCon Paris 2014
 
maximize app engagement and monetization - DroidCon Paris 2014
maximize app engagement and monetization - DroidCon Paris 2014maximize app engagement and monetization - DroidCon Paris 2014
maximize app engagement and monetization - DroidCon Paris 2014
 
Using the android ndk - DroidCon Paris 2014
Using the android ndk - DroidCon Paris 2014Using the android ndk - DroidCon Paris 2014
Using the android ndk - DroidCon Paris 2014
 
Holo material design transition - DroidCon Paris 2014
Holo material design transition - DroidCon Paris 2014Holo material design transition - DroidCon Paris 2014
Holo material design transition - DroidCon Paris 2014
 
Death to passwords - DroidCon Paris 2014
Death to passwords - DroidCon Paris 2014Death to passwords - DroidCon Paris 2014
Death to passwords - DroidCon Paris 2014
 
Google glass droidcon - DroidCon Paris 2014
Google glass droidcon - DroidCon Paris 2014Google glass droidcon - DroidCon Paris 2014
Google glass droidcon - DroidCon Paris 2014
 
Embedded webserver implementation and usage - DroidCon Paris 2014
Embedded webserver implementation and usage - DroidCon Paris 2014Embedded webserver implementation and usage - DroidCon Paris 2014
Embedded webserver implementation and usage - DroidCon Paris 2014
 
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
 
What's new in android 4.4 - Romain Guy & Chet Haase
What's new in android 4.4 - Romain Guy & Chet HaaseWhat's new in android 4.4 - Romain Guy & Chet Haase
What's new in android 4.4 - Romain Guy & Chet Haase
 
Efficient Image Processing - Nicolas Roard
Efficient Image Processing - Nicolas RoardEfficient Image Processing - Nicolas Roard
Efficient Image Processing - Nicolas Roard
 
Build a user experience by Eyal Lezmy
Build a user experience by Eyal LezmyBuild a user experience by Eyal Lezmy
Build a user experience by Eyal Lezmy
 

Dernier

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 

Dernier (20)

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 

Robotium vs Espresso: Get ready to rumble ! - DroidCon Paris 2014

  • 1.
  • 2.
  • 3. Robotiumvs Espresso Get ready to rumble !
  • 4.
  • 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_
  • 29.
  • 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_
  • 51.
  • 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_
  • 113.
  • 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_
  • 131.
  • 133.