+ All Categories
Home > Software > Espresso devoxx 2014

Espresso devoxx 2014

Date post: 05-Jul-2015
Category:
Upload: xebia-france
View: 292 times
Download: 0 times
Share this document with a friend
Description:
Your Robotium tests are flaky? not readable? Come to this Tools in Action and discover Espresso, the new testing library for Android. During this live coding presentation, you will learn how to write beautiful tests and take advantage of Espresso features. Par Thomas Guérin, consultant chez Xebia, à Devoxx Belgique 2014.
42
@Tom404_ #Devoxx #AndroidEspresso Espresso: What else ? Thomas Guerin Xebia France
Transcript
Page 1: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Espresso: What else ?Thomas Guerin Xebia France

Page 2: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Page 3: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

Page 4: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

“Testing is sometimes complicated !”

Page 5: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

“Testing is sometimes complicated !”

“My tests randomly fail !”

Page 6: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

“Testing is sometimes complicated !”

“My tests randomly fail !”

“I have to fix the tests for a simple modification in my code”

Page 7: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

“Testing is sometimes complicated !”

“My tests randomly fail !”

“I have to fix the tests for a simple modification in my code”

Page 8: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

“Testing is sometimes complicated !”

“My tests randomly fail !”

“I have to fix the tests for a simple modification in my code”

Page 9: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

“My tests last hours !”

“Testing is sometimes complicated !”

“My tests randomly fail !”

“I have to fix the tests for a simple modification in my code”

Page 10: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

A test must be …

Page 11: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

A test must be …

Simple

Page 12: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

A test must be …

FastSimple

Page 13: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

A test must be …

FastSimple Reliable

Page 14: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

A test must be …

FastSimple Reliable Durable

Page 15: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

//  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);

Bad example

Page 16: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

//  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);

Bad example

Page 17: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Robotium

Page 18: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API Overview

Page 19: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API Overview

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)

Page 20: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

solo.clickOnView(R.id.start_activity_button);  

//  Wait  for  a  specific  condition  to  occur    solo.waitForCondition(new  Condition()  {                          @Override                          public  boolean  isSatisfied()  {                                  return  checkConditionInNewActivity();                          }                  },  Timeout.getSmallTimeout());  

solo.clickOnView(R.id.view_in_new_activity);  

Basic example

Page 21: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

solo.clickOnView(R.id.start_activity_button);  

//  Wait  for  a  specific  condition  to  occur    solo.waitForCondition(new  Condition()  {                          @Override                          public  boolean  isSatisfied()  {                                  return  checkConditionInNewActivity();                          }                  },  Timeout.getSmallTimeout());  

solo.clickOnView(R.id.view_in_new_activity);  

Basic example

Page 22: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Robotium drawbacksFlaky tests

Hard to extend

View index based methods

Errors not meaningful

Page 23: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Espresso

Page 24: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Hamcrest

Page 25: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

HamcrestLibrary of matchers

Page 26: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

HamcrestLibrary of matchers

assertThat("Hello",  equalTo("Hello"))  

//  Syntaxic  sugar  assertThat("Hello",  is("Hello"))  

//  A  lot  of  matchers  available  allOf    not    instanceOf    hasProperty    equalToIgnoringCase

Page 27: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

HamcrestLibrary of matchers

assertThat("Hello",  equalTo("Hello"))  

//  Syntaxic  sugar  assertThat("Hello",  is("Hello"))  

//  A  lot  of  matchers  available  allOf    not    instanceOf    hasProperty    equalToIgnoringCase

Easy to compose

Page 28: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

public  static  Matcher<View>  isVisible()  {          return  new  TypeSafeMatcher<View>()  {              @Override              public  void  describeTo(Description  description)  {                  description.appendText("is  view  visible");              }  

           @Override              public  boolean  matchesSafely(View  view)  {                  return  view.getVisibility()  ==  View.VISIBLE;              }          };  }

Custom matcher

Page 29: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API overview

Page 30: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API overview

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

Espresso

Page 31: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API overview

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

Espresso withId()withText(text)

hasSibling(Matcher<View>)

ViewMatchers

Page 32: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API overview

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

Espresso

perform(ViewAction)check(ViewAssertion)

ViewInteraction / DataInteraction

withId()withText(text)

hasSibling(Matcher<View>)

ViewMatchers

Page 33: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API overview

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

Espresso

perform(ViewAction)check(ViewAssertion)

ViewInteraction / DataInteraction

click()typeText(text)

ViewActions

withId()withText(text)

hasSibling(Matcher<View>)

ViewMatchers

Page 34: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

API overview

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>)

ViewMatchers

Page 35: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakiness

Page 36: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakinessFor each test action, Espresso will :

Page 37: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakinessFor each test action, Espresso will :

1. Wait until the app is idle

Page 38: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakinessFor each test action, Espresso will :

1. Wait until the app is idle2. Run on the UI thread

Page 39: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakinessFor each test action, Espresso will :

1. Wait until the app is idle2. Run on the UI thread3. Wait until completion

Page 40: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakinessFor each test action, Espresso will :

1. Wait until the app is idle2. Run on the UI thread3. Wait until completion4. Check the result

Page 41: Espresso devoxx 2014

@Tom404_#Devoxx #AndroidEspresso

Goodbye flakinessFor each test action, Espresso will :

1. Wait until the app is idle2. Run on the UI thread3. Wait until completion4. Check the result

Page 42: Espresso devoxx 2014

Demo

@Tom404_#Devoxx #AndroidEspresso


Recommended