droidcon 2014 - robotium vs espresso_droidcon

Post on 05-Dec-2014

111 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

Robotium vs EspressoGet ready to rumble !

Thomas Guerin

Thomas GuerinDéveloppeur Android

Thomas GuerinDéveloppeur Android

Tests addict

Thomas GuerinDéveloppeur Android

Tests addictNiveau 15 à Destiny

Robotium vs Espresso : Get ready to rumble !

Robotium vs Espresso : Get ready to rumble !

Pourquoi ne pas faire de tests ?

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Pourquoi ne pas faire de tests ?

“Mes tests durent des heures !”

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Pourquoi ne pas faire de tests ?

“Mes tests durent des heures !”

#Droidcon #Robotium #Espresso

“Tester ce n’est pas toujours simple !”

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Pourquoi ne pas faire de tests ?

“Mes tests durent des heures !”

#Droidcon #Robotium #Espresso

“Tester ce n’est pas toujours simple !”

“Mes tests échouent aléatoirement !”

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Pourquoi ne pas faire de tests ?

“Mes tests durent des heures !”

#Droidcon #Robotium #Espresso

“Tester ce n’est pas toujours simple !”

“Mes tests échouent aléatoirement !”

“Je vais devoir corriger les tests alors que je n’ai presque rien modifié”

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Un test doit être…

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Un test doit être…

#Droidcon #Robotium #Espresso

Simple

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Un test doit être…

#Droidcon #Robotium #Espresso

RapideSimple

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Un test doit être…

#Droidcon #Robotium #Espresso

RapideSimple Fiable

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Un test doit être…

#Droidcon #Robotium #Espresso

RapideSimple Fiable Durable

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Un mauvais exemple

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Un mauvais exemple

#Droidcon #Robotium #Espresso

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

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Un mauvais exemple

#Droidcon #Robotium #Espresso

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

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Les combattants

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Les combattants

#Droidcon #Robotium #Espresso

Robotium

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Les combattants

#Droidcon #Robotium #Espresso

VS

Robotium Espresso

@Tom404_

Préparation

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Dépendances Gradle

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Dépendances Gradle

#Droidcon #Robotium #Espresso

dependencies { androidTestCompile ‘com.jayway.android.robotium:robotium-solo:5.2.1' androidTestCompile 'com.squareup.assertj:assertj-android:1.0.0' }

Robotium

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Dépendances Gradle

#Droidcon #Robotium #Espresso

android.packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' }

dependencies { /* Jars récupérés depuis https://code.google.com/p/android-test-kit */ androidTestCompile files(‘libs/espresso-1.1.jar’, ‘libs/espresso-contrib-1.1.jar', ‘libs/testrunner-1.1.jar', 'libs/testrunner-runtime-1.1.jar') androidTestCompile 'com.google.guava:guava:14.0.1', 'com.squareup.dagger:dagger:1.1.0', 'org.hamcrest:hamcrest-core:1.1', 'org.hamcrest:hamcrest-integration:1.1', 'org.hamcrest:hamcrest-library:1.1' }

Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Dépendances Gradle

#Droidcon #Robotium #Espresso

android.packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' }

dependencies { androidTestCompile ’com.jakewharton.espresso:espresso:1.1-r3’, ‘com.jakewharton.espresso:espresso-support-v4:1.1-r3' }

https://github.com/JakeWharton/double-espresso

Double Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Test Runner

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Test Runner

#Droidcon #Robotium #Espresso

Robotium utilise le test runner du sdk

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Test Runner

#Droidcon #Robotium #Espresso

Robotium utilise le test runner du sdk

Espresso nécessite un test runner spécifique

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Test Runner

#Droidcon #Robotium #Espresso

Robotium utilise le test runner du sdk

Espresso nécessite un test runner spécifique

defaultConfig { testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner" }

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

GoogleInstrumentationTestRunner

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

GoogleInstrumentationTestRunner

#Droidcon #Robotium #Espresso

onCreate de l'application finalisée avant le début des tests

@Tom404_

Robotium vs Espresso : Get ready to rumble !

GoogleInstrumentationTestRunner

#Droidcon #Robotium #Espresso

onCreate de l'application finalisée avant le début des tests

Instrumentation terminée == activités finies

@Tom404_

Robotium vs Espresso : Get ready to rumble !

GoogleInstrumentationTestRunner

#Droidcon #Robotium #Espresso

onCreate de l'application finalisée avant le début des tests

Instrumentation terminée == activités finies

Monitoring des activités plus fiable

@Tom404_

Robotium vs Espresso : Get ready to rumble !

GoogleInstrumentationTestRunner

#Droidcon #Robotium #Espresso

onCreate de l'application finalisée avant le début des tests

Instrumentation terminée == activités finies

Monitoring des activités plus fiable

Peut être utilisé avec d'autres librairies

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Initialisation

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Initialisation

#Droidcon #Robotium #Espresso

Robotiumpublic class SimpleActionsTest extends ActivityInstrumentationTestCase2<MainActivity> { ! private Solo solo; ! public void setUp() throws Exception { super.setUp(); solo = new Solo(getInstrumentation(), getActivity()); } ! public void tearDown() throws Exception { solo.finishOpenedActivities(); super.tearDown(); } }

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Initialisation

#Droidcon #Robotium #Espresso

public class SimpleActionsTest extends ActivityInstrumentationTestCase2<MainActivity> { ! @Override protected void setUp() throws Exception { super.setUp(); // Espresso ne va pas lancer l'activité pour nous getActivity(); } }

Espresso

@Tom404_

Expressivité

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

Robotium

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

Solo

Robotium

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

Solo

getView(int viewId)

drag(…)

clickInList(int line, int index)

goBack()setNavigationDrawer(int status)pressSoftKeyboardNextButton()

clickOnActionBarItem(int id)

scrollToBottom() searchEditText(String text)

pressSoftKeyboardSearchButton()

getButton(int index)scrollDown()clearEditText(int index)

clickOnToggleButton(String text)

clickOnImageButton(int index)

clickOnButton(int index)

pressMenuItem(int index)

clickOnActionBarHome()

scrollDownList(int index)

searchText(String text)

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso

// Récupération de la vue Button myButton = (TextView) solo.getView(R.id.my_button); !// Assertions (AssertJ Android) assertThat(myButton).hasText(“My button”).isVisible(); !// Clic sur la vue solo.clickOnView(myButton)

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest

#Droidcon #Robotium #Espresso

Librairie de matchers

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest

#Droidcon #Robotium #Espresso

Librairie de matchersassertThat("Hello", equalTo("Hello"))

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest

#Droidcon #Robotium #Espresso

Librairie de matchersassertThat("Hello", equalTo("Hello"))!// Sucre syntaxique assertThat(“Hello", is("Hello"))

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest

#Droidcon #Robotium #Espresso

Librairie de matchersassertThat("Hello", equalTo("Hello"))!// Sucre syntaxique assertThat(“Hello", is("Hello"))!// De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest

#Droidcon #Robotium #Espresso

Librairie de matchersassertThat("Hello", equalTo("Hello"))!// Sucre syntaxique assertThat(“Hello", is("Hello"))

Possibilité de composition

!// De nombreux matchers disponibles allOf not instanceOf hasProperty equalToIgnoringCase

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest custom matcher

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Hamcrest custom matcher

#Droidcon #Robotium #Espresso

public class IsNotANumber extends TypeSafeMatcher<Double> { ! @Override public boolean matchesSafely(Double number) { return number.isNaN(); } ! public void describeTo(Description description) { description.appendText("not a number"); } ! public static Matcher<Double> notANumber() { return new IsNotANumber(); } !}

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso

Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso withId()!withText(text)!

hasSibling(Matcher<View>)

ViewMatchersEspresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso

click()!typeText(text)

ViewActions

withId()!withText(text)!

hasSibling(Matcher<View>)

ViewMatchersEspresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso

click()!typeText(text)

ViewActions

doesNotExist()!matches(Matcher<View>)

ViewAssertions

withId()!withText(text)!

hasSibling(Matcher<View>)

ViewMatchersEspresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso

perform(ViewAction)!check(ViewAssertion)

ViewInteraction / DataInteraction

click()!typeText(text)

ViewActions

doesNotExist()!matches(Matcher<View>)

ViewAssertions

withId()!withText(text)!

hasSibling(Matcher<View>)

ViewMatchersEspresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso

perform(ViewAction)!check(ViewAssertion)

ViewInteraction / DataInteraction

click()!typeText(text)

ViewActions

doesNotExist()!matches(Matcher<View>)

ViewAssertions

withId()!withText(text)!

hasSibling(Matcher<View>)

ViewMatchersEspresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

API overview

#Droidcon #Robotium #Espresso

onView(Matcher<View>)!onData(Matcher<Object>

Espresso

perform(ViewAction)!check(ViewAssertion)

ViewInteraction / DataInteraction

click()!typeText(text)

ViewActions

doesNotExist()!matches(Matcher<View>)

ViewAssertions

withId()!withText(text)!

hasSibling(Matcher<View>)

ViewMatchersEspresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso

onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso

onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click());!// Une simple extraction de méthode permet de simplifier onView(withIdAndText(R.id.my_button, "My Button”)) .check(matches(isDisplayed())) .perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso

onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click());!// Une simple extraction de méthode permet de simplifier onView(withIdAndText(R.id.my_button, "My Button”)) .check(matches(isDisplayed())) .perform(click());!// Si le bouton n'est pas affiché le perform(click()) échouera onView(withIdAndText(R.id.my_button, "My Button")).perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Exemple

#Droidcon #Robotium #Espresso

onView(allOf(withId(R.id.my_button), withText(“My Button”))) .check(matches(isDisplayed())) .perform(click());

Manque de restrictions = AmbiguousViewMatcherException

!// Une simple extraction de méthode permet de simplifier onView(withIdAndText(R.id.my_button, "My Button”)) .check(matches(isDisplayed())) .perform(click());!// Si le bouton n'est pas affiché le perform(click()) échouera onView(withIdAndText(R.id.my_button, "My Button")).perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Listview

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Listview

#Droidcon #Robotium #Espresso

// Clic sur item solo.clickOnText("textToFind"); !// Si jamais il y'en a plusieurs -> utilisation d'un index solo.clickOnText("textToFind", 3); !// Ou choisir directement la ligne solo.clickInList(2);

Robotium

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Listview

#Droidcon #Robotium #Espresso

onData(allOf(is(instanceOf(String.class)), is("textToFind"))).perform(click()); !// Ou directement à une position onData(is(instanceOf(String.class))).atPosition(0).perform(click()); !// Possibilité de préciser une listview, utile pour le view pager onData(allOf(is(instanceOf(String.class)), is("textToFind"))) .inAdapterView(withId(R.id.my_list)).perform(click()); !// Interaction avec une vue enfant de la ligne onData(allOf(is(instanceOf(String.class)), is("textToFind"))) .onChildView(withId(R.id.my_child)) .perform(click());

Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Listview

#Droidcon #Robotium #Espresso

// Type renvoyé par la méthode getItem de l'adapteur public class Item { public String name; public String itemContent; }

Espresso : cas plus complexe

!onData(allOf(is(instanceOf(Item.class)), hasProperty(“name", equalTo(“nameToFind")))) .perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Listview

#Droidcon #Robotium #Espresso

public static Matcher<Object> withItemName(final Matcher<String> itemTextMatcher){ return new BoundedMatcher<Object, Item>(Item.class) { @Override public boolean matchesSafely(Item item) { return itemTextMatcher.matches(item.name); } ! @Override public void describeTo(Description description) { description.appendText("with item name: "); itemTextMatcher.describeTo(description); } }; }

Espresso : custom matcher

onData(withItemName(equalTo("nameToFind"))).perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Webview

#Droidcon #Robotium #Espresso

Robotium

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Webview

#Droidcon #Robotium #Espresso

RobotiumPossibilité d’interagir avec les webviews

•solo.getWebElements(by)•solo.clickOnWebElement(by)

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Webview

#Droidcon #Robotium #Espresso

RobotiumPossibilité d’interagir avec les webviews

•solo.getWebElements(by)•solo.clickOnWebElement(by)

Plusieurs types de recherches disponibles•By.id(String id)•By.className(String className)•By.textContent(String textContent)•By.name(String name)

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Webview

#Droidcon #Robotium #Espresso

Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Webview

#Droidcon #Robotium #Espresso

Espresso

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Navigation Drawer

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Navigation Drawer

#Droidcon #Robotium #Espresso

Robotium// Attention l'id du frame layout du menu doit absolument être "left_drawer" solo.setNavigationDrawer(Solo.OPENED); !solo.setNavigationDrawer(Solo.CLOSED);

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Navigation Drawer

#Droidcon #Robotium #Espresso

Robotium// Attention l'id du frame layout du menu doit absolument être "left_drawer" solo.setNavigationDrawer(Solo.OPENED); !solo.setNavigationDrawer(Solo.CLOSED);

EspressoDrawerActions.openDrawer(R.id.drawer_layout); !DrawerActions.closeDrawer(R.id.drawer_layout);

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Action bar

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Action bar

#Droidcon #Robotium #Espresso

Robotiumsolo.clickOnActionBarItem(R.id.action_example); !// Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action");

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Action bar

#Droidcon #Robotium #Espresso

Robotiumsolo.clickOnActionBarItem(R.id.action_example); !// Cas de l'action bar overflow solo.sendKey(KeyEvent.KEYCODE_MENU); solo.clickOnText("action");

EspressoonView(withId(R.id_action_example)).perform(click()); !// Cas de l'action bar overflow openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); onView(withText("action")).perform(click());

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Back button & Keyboard

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Back button & Keyboard

#Droidcon #Robotium #Espresso

Robotiumsolo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Back button & Keyboard

#Droidcon #Robotium #Espresso

Robotiumsolo.goBack(); // solo.goBack() est aussi utilisé pour fermer le clavier

EspressoEspresso.pressBack(); Espresso.closeSoftKeyboard();

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Les messages d’erreur

#Droidcon #Robotium #Espresso @Tom404_

Robotium

!junit.framework.AssertionFailedError: View with id: '1234' is not found! at com.robotium.solo.Solo.getView(Solo.java:2008) at com.robotium.solo.Solo.getView(Solo.java:1988) at fr.droidcon.robotium.vs.espresso.samples.test.robotium.SimpleActionsTest.testClickButton(SimpleActionsTest.java:28)

!// Récupération d’une vue inexistante solo.getView(1234);

Robotium vs Espresso : Get ready to rumble !

Les messages d’erreur

#Droidcon #Robotium #Espresso @Tom404_

com.google.android.apps.common.testing.ui.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: is <1234> If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:android.widget.ListView{426f6f18 VFED.VC. ......ID 0,0-720,1557} - android.widget.ListView{4269c598 V.ED.VC. ........ 48,393-1032,1509 #7f070042 app:id/my_list} !View Hierarchy: +>DecorView{id=-1, visibility=VISIBLE, width=1080, height=1776, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1} | +->ActionBarOverlayLayout{id=16909075, res-name=action_bar_overlay_layout, visibility=VISIBLE, width=1080, height=1776, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3} | +-->FrameLayout{id=16908290, res-name=content, visibility=VISIBLE, width=1080, height=1557, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-

Espresso!// Récupération d’une vue inexistante onView(withId(1234));

Robotium vs Espresso : Get ready to rumble !

Les messages d’erreur

#Droidcon #Robotium #Espresso @Tom404_

Enchaînements

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Wait and See

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Wait and See

#Droidcon #Robotium #Espresso

Robotium repose sur le principe de wait & see•solo.waitForActivity(Class class, int timeout)• solo.waitForCondition(Condition condition, int timeout)• solo.waitForDialogToOpen()

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Wait and See

#Droidcon #Robotium #Espresso

solo.clickOnView(R.id.start_activity_button); !// On attend que la vue apparaisse avant d'agir solo.waitForView(R.id.view_in_new_activity); !solo.clickOnView(R.id.view_in_new_activity);

Robotium repose sur le principe de wait & see•solo.waitForActivity(Class class, int timeout)• solo.waitForCondition(Condition condition, int timeout)• solo.waitForDialogToOpen()

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Finis de dormir !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Finis de dormir !

#Droidcon #Robotium #Espresso

Entrée en jeu du GoogleInstrumentationTestRunner

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Finis de dormir !

#Droidcon #Robotium #Espresso

Entrée en jeu du GoogleInstrumentationTestRunner

Monitoring plus fin des activités et des ressources

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Finis de dormir !

#Droidcon #Robotium #Espresso

Entrée en jeu du GoogleInstrumentationTestRunner

Monitoring plus fin des activités et des ressources

Analyse du ThreadUI pour savoir quand agir

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Finis de dormir !

#Droidcon #Robotium #Espresso

Entrée en jeu du GoogleInstrumentationTestRunner

Monitoring plus fin des activités et des ressources

Analyse du ThreadUI pour savoir quand agir

Pas de wait

@Tom404_

Robotium vs Espresso : Get ready to rumble !

Finis de dormir !

#Droidcon #Robotium #Espresso

onView(withId(R.id.start_activity_button)).perform(click()); !onView(withId(R.id.view_in_new_activity)).perform(click());

Entrée en jeu du GoogleInstrumentationTestRunner

Monitoring plus fin des activités et des ressources

Analyse du ThreadUI pour savoir quand agir

Pas de wait

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Idle mais actif !

#Droidcon #Robotium #Espresso @Tom404_

Robotium vs Espresso : Get ready to rumble !

Idle mais actif !

#Droidcon #Robotium #Espresso

Possibilité d'enregistrer des idlingResources

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso

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

@Tom404_

Robotium vs Espresso : Get ready to rumble !

#Droidcon #Robotium #Espresso

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

Espresso.registerIdlingResources(espressoThreadPool);

@Tom404_

Conclusion

Questions ?

top related