Unit	
  Tes)ng	
  on	
  Android	
  
Danny	
  Preussler	
  
GROUPON	
  
DroidCon	
  Dubai	
  
test	
  (c)	
  DaveBleasdale,	
  CC	
  by	
  2.0,	
  www.flickr.com/photos/sidelong/246816211	
  
Groupon	
  is	
  the	
  global	
  	
  
leader	
  in	
  local	
  commerce,	
  
making it easy for people around the world to search !
and discover great businesses at unbeatable prices.

Source: Internal data,, March 2014
WORLDWIDE!
260M+ subscribers 53.9M active customers 500+ markets 900M+ deals sold
2
$5B+ in annual billings 12,000+ global employees
Leading	
  the	
  way	
  in	
  mobile	
  commerce	
  
Our mobile app is available in 43 countries. 
Groupon’s vibrant mobile marketplace connects!
consumers with their local economy
3	
  
Sources: Internal Data; iTunes ranking for US stores available here - https://itunes.apple.com/WebObjects/
MZStore.woa/wa/viewFeature?id=500873243&mt=8&v0=www-itunes25Bcountdown-appstore 
Nearly 110 million people worldwide have
downloaded our mobile app at the end of Q4 2014.
One of the 25 most downloaded free
apps of all time
More than 50% of our Global transactions were
completed on a mobile device by the end of Q4
2014
About Me?
•  Groupon Berlin
•  Groupon Merchant App
•  Unit Test enthusiast
What	
  people	
  say	
  about	
  unit	
  tes0ng	
  
•  Slows	
  you	
  down	
  
•  I	
  know	
  my	
  code	
  
is	
  working!	
  
•  Only	
  have	
  UI	
  Code	
  
Day	
  27/365	
  -­‐	
  Imagina)on..	
  by	
  Caden	
  Crawford,	
  CC	
  by	
  2.0,	
  flickr.com/
photos/cadencrawford/8422302030	
  
What is a Unit Test?
•  Small	
  
Opposite	
  of	
  an	
  end-­‐to-­‐end-­‐test	
  
test	
  the	
  smallest	
  unit	
  possible	
  
•  You	
  should	
  have	
  LOTS	
  of	
  them	
  
•  Fast!!!!	
  
er	
  by	
  www.GlynLowe.com,	
  CC	
  by	
  2.0,	
  flickr.com/photos/glynlowe/10921728045	
  
Why	
  Unit	
  test? 	
  	
  
•  Documents	
  behaviour	
  
	
  
•  Refactoring	
  not	
  possible	
  	
  
without!	
  
	
  
•  Gives	
  trust	
  
	
  
•  Only	
  slows	
  down	
  	
  
if	
  you	
  don‘t	
  have	
  )me	
  	
  
for	
  quality	
  code	
  and	
  tes)ng	
  anyway	
  
Day	
  27/365	
  -­‐	
  Imagina)on..	
  by	
  Caden	
  Crawford,	
  CC	
  by	
  2.0,	
  	
  
flickr.com/photos/cadencrawford/8422302030	
  
Why	
  Unit	
  test? 	
  	
  
Code	
  without	
  Test	
  =	
  Legacy	
  code	
  
	
  
Only	
  Bad	
  Code	
  is	
  untestable!	
  
	
  
Day	
  27/365	
  -­‐	
  Imagina)on..	
  by	
  Caden	
  Crawford,	
  CC	
  by	
  2.0,	
  	
  
flickr.com/photos/cadencrawford/8422302030	
  
SOLID
FOUNDATIONFlughafen Berlin-Brandenburg, Blick in die Abflughalle by Muns CC BY 3.0
http://commons.wikimedia.org/wiki/File:120513-BER-innen.JPG
App development reality
Tidy garage by Bryn Pinzgauer CC 2.0
http://www.flickr.com/photos/12394349@N06/4492572621/in/photostream/
Pure JUnit?
java.lang.RuntimeException: Stub!
Android Firewall by Uncalno, CC BY 2.0 flickr.com/photos/uncalno/8538679708
Robolectric
New Android Unit Testing
Lost	
  Horizons	
  -­‐	
  Light	
  by	
  Simon	
  &	
  His	
  Camera,	
  CC	
  by	
  2.0	
  flickr.com/ph
New Android Unit Testing	
  
•  still experimental
•  hdp://tools.android.com/tech-­‐docs/unit-­‐tes)ng-­‐support	
  
•  Project	
  structure:	
  
	
  	
  	
  	
  src/main/java/Foo.java	
  
	
  	
  	
  	
  src/test/java/FooTest.java
•  gradle:	
  
android {
testOptions {
	
   	
   unitTests.returnDefaultValues = true
}
Lost	
  Horizons	
  -­‐	
  Light	
  by	
  Simon	
  &	
  His	
  Camera,	
  CC	
  by	
  2.0	
  flickr.com/photos/simon__syon/14842606832	
  
What	
  to	
  test?	
  
Start	
  your	
  engine	
  by	
  Norlando	
  Pobre,	
  CC	
  by	
  2.0,	
  flickr.com/photos/npobre/2601582256	
  
Great Wall of China (IV) by isawnyu. CC 2.0 http://
www.flickr.com/photos/isawnyu/7183821643/in/photostream/
Separate Java and Android Code?
Great Wall of China (IV) by isawnyu. CC 2.0 http://
www.flickr.com/photos/isawnyu/7183821643/in/photostream/
Separate Java and Android Code?
Android is not Java+UI
Intent, Bundle, SparseArray, Uri.. not fancy device classes!
You will never reuse this on another Java platform,
stop pretending!
Context everywhere
Recreate the System? (interface UI {...} ?)
You	
  can	
  test	
  everything!	
  
Typing	
  the	
  universe	
  by	
  Feliciano	
  Guimarães,	
  CC	
  by	
  2.0,	
  flickr.com/photos/jsome1/6097841770	
  
„Mock“???	
  
Martin Fowler:
„test-doubles ... pre-programmed with
expectations “
Typing	
  the	
  universe	
  by	
  Feliciano	
  Guimarães,	
  CC	
  by	
  2.0,	
  flickr.com/photos/jsome1/6097841770	
  
Typing	
  the	
  universe	
  by	
  Feliciano	
  Guimarães,	
  CC	
  by	
  2.0,	
  flickr.com/photos/jsome1/6097841770	
  
Mock	
  
TelephonyManager mgr =
mock(TelephonyManager.class);
when(mgr.getDeviceId())
.thenReturn("123456");
...
	
  
Spy	
  
MyPreferences pref =
spy(new MyPreferences(context));
…
verify(pref).saveTitle(same(title));
verify(pref).savePersonalData(anyString());
	
  
	
  
She	
  spy	
  by	
  Kangrex,	
  CC	
  by	
  2.0;	
  flickr.com/photos/kangrex/3012574701	
  
Building blocks of a Test	
  
public class AndroidAccountsTest {
AccountManager manager;
AndroidAccounts tested;	
  
@Before
public void setup() {...}
@Test
public void should_get_token() {
when(manager.peekAuthToken(....)).thenReturn("token");
String token = tested.getCurrentToken(...)
assertEquals("token", token);
}
}
swivel-­‐snot	
  by	
  Linus	
  Bohman,	
  CC	
  2.0,	
  flickr.com/photos/bohman/16062901379	
  
Easy...	
  
•  Test	
  u)lity	
  classes	
  
	
  
•  Test	
  JSON	
  parsing	
  
	
  
•  Test	
  API	
  layer	
  
	
  
Duplo	
  Pac-­‐Man	
  by	
  Dan	
  Diemer,	
  CC	
  by	
  2.0,	
  flickr.com/photos/diemer/192740446	
  
Gson gson = GsonFactory.getGson();
@Test
public void should_parse_json_data() {
String values = inputStreamToString(„auth.json"));
AuthRslt rslt = gson.fromJson(values, AuthRslt.class);
assertEquals("AQAAAABwgQ2vVzk-KjiEA3“,
result.getAccessToken());
}
Easy...	
  
Duplo	
  Pac-­‐Man	
  by	
  Dan	
  Diemer,	
  CC	
  by	
  2.0,	
  flickr.com/photos/diemer/192740446	
  
Easy	
  when	
  you	
  do	
  it	
  right	
  
•  Test	
  user	
  interac)on	
  (click	
  etc)	
  
•  Test	
  Fragments	
  and	
  Ac)vi)es	
  
	
  
Lego	
  small	
  car.	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6805370739	
  
class NavFragment extends InjectedFragment {
Interactor interactor;
@OnClick(R.id.nav_button_checkout)
public void onClickCheckout() {
interactor.moveToCheckout(
getActivity());
}
}
User	
  interac)on	
  
Lego	
  small	
  car.	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6805370739	
  
Test	
  for	
  this	
  is	
  trivial!	
  
Screen	
  changes	
  
@Test
public void should_do_transaction() {
TransactionUtil transactionsUtil =
mock(TransactionUtil.class),
tested.showPaymentMethods(
transactionsUtil, mock(Purchase.class));
verify(transactionsUtil)
.addAllowingStateLoss(
any(FragmentManager.class),
eq(android.R.id.content),
isA(PaymentFragment.class));
}
Lego	
  small	
  car.	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6805370739	
  
Screen	
  changes	
  
Lego	
  small	
  car.	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6805370739	
  
•  Robolectric	
  offers	
  FragmentTranscta)ons	
  and	
  
life	
  cycle	
  method:	
  
•  Robolectric
.buildActivity(
Activity.class)
.attach()
.create().....
•  Careful,	
  feature	
  flaky	
  
Screen	
  changes	
  
Lego	
  small	
  car.	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6805370739	
  
•  Easier:	
  
Field field =
Fragment.class.getDeclaredField("mActivity");
field.setAccessible(true);
field.set(fragmentInstance, mock(Activity.class);
•  You	
  might	
  need	
  also	
  to	
  mock	
  getResources()
Harder	
  but	
  possible	
  
•  Test	
  UI	
  code	
  
	
  
LEGO	
  10179	
  Ul)mate	
  Collector's	
  Millenium	
  Falcon™	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6966161598	
  
Test	
  UI	
  code	
  
public class BorderPainterTest {
Canvas canvas = mock(Canvas.class);
Circle circle = mock(Circle.class);
BorderPainter tested = new BorderPainter();
@Test
public void should_draw_two_circles() {
...
tested.drawBorder(new RectF(), canvas, circle);
InOrder inOrder = inOrder(canvas);
inOrder.verify(canvas).drawCircle(
anyFloat(), anyFloat(), eq(10f), any(Paint.class));
inOrder.verify(canvas).drawCircle(
anyFloat(), anyFloat(), eq(20f), any(Paint.class));
}
}
LEGO	
  10179	
  Ul)mate	
  Collector's	
  Millenium	
  Falcon™	
  by	
  Do-­‐Hyun	
  Kim,	
  CC	
  by	
  2.0,	
  flickr.com/photos/s)ckkim/6966161598	
  
Wri)ng	
  testable	
  code...	
  
•  Clean	
  Code	
  
•  Separa)on	
  	
  
of	
  Concerns	
  
Manual	
  Inside	
  by	
  Masked	
  Builder,	
  CC	
  by	
  2.0,	
  flickr.com/photos/masked-­‐builder/8517238602	
  
Dependency	
  Injec)on	
  helps	
  
•  Don‘t	
  create	
  dependencies	
  yourself	
  
•  Invert	
  Control!	
  
	
  
•  Inject	
  them!	
  
construct	
  by	
  Len	
  Madhews,	
  CC	
  by	
  2.0;	
  flickr.com/photos/mythoto/16412713709	
  
Syringe	
  with	
  Green	
  Liquid	
  by	
  Andres	
  Rueda,	
  CC	
  by	
  2.0;	
  lickr.com/photos/andresrueda/16558374828	
  
If	
  it‘s	
  hard	
  to	
  test...	
  
•  Class	
  is	
  too	
  large	
  
•  Class	
  is	
  doing	
  too	
  many	
  things	
  
•  Class	
  knows	
  too	
  many	
  things	
  
Modified	
  condi)on/decision	
  coverage	
  for	
  cri)cal	
  souware	
  tes)ng	
  by	
  Nguyen	
  Hung	
  Vu,	
  CC	
  by	
  2.0,	
  www.flickr.com/photos/vuhung/14621502361	
  
Make	
  it	
  fail!	
  
Apple	
  Mini	
  DisplayPort	
  adapter	
  FAIL	
  by	
  David	
  Joyce,	
  
CC	
  by	
  2.0,	
  flickr.com/photos/deapeajay/2969264395	
  
1	
  method	
  =	
  1	
  test?	
  
•  Test	
  all	
  cases,	
  else	
  you	
  might	
  miss	
  sth	
  
•  one	
  method	
  should	
  have	
  mul)ple	
  test	
  	
  
(although	
  coverage	
  already	
  reached	
  with	
  first)	
  
•  Don‘t	
  be	
  super	
  strict	
  on	
  units,	
  	
  
some)mes	
  end	
  to	
  end	
  might	
  make	
  sense	
  
i.e.	
  json	
  parsing	
  into	
  models	
  with	
  full	
  Json	
  
	
  
Coverage?	
  
• You	
  should	
  Measure	
  	
  
• Mo)vates!	
  
• Don‘t	
  trust	
  too	
  much	
  into	
  it	
  
When	
  to	
  use	
  Robolectric	
  
•  Parcel	
  Tests	
  
•  Arguments/Bundle	
  Tests	
  
•  Resource	
  loading	
  Tests	
  
Parcel	
  Tests	
  with	
  Robolectric	
  
@RunWith(RobolectricTestRunner.class)	
  
public	
  class	
  UserTest	
  {	
  
	
  	
  	
  	
  Parcel	
  parcel	
  =	
  Parcel.obtain();	
  
	
  	
  	
  	
  User	
  tested	
  =	
  new	
  User("123",	
  "456");	
  
	
  
	
  	
  	
  	
  @Test	
  
	
  	
  	
  	
  public	
  void	
  check_parcel_implementa)on()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  tested.writeToParcel(parcel,	
  0);	
  
	
  	
  	
  	
  	
  	
  	
  	
  parcel.setDataPosi)on(0);	
  
	
  	
  	
  	
  	
  	
  	
  	
  User	
  out	
  =	
  User.CREATOR.createFromParcel(parcel);	
  
	
  	
  	
  	
  	
  	
  	
  	
  assertEquals("123",	
  out.getUser());	
  
	
  	
  	
  	
  	
  	
  	
  	
  assertEquals("456",	
  out.getPassword());	
  
	
  	
  	
  	
  }	
  
Resource	
  Tests	
  with	
  Robolectric	
  
@Test	
  
@Config(qualifiers	
  =	
  "en")	
  
public	
  void	
  getTotalAuerTaxLong()	
  {	
  
	
  	
  	
  	
  assertEquals(	
  
	
   	
  "$10.00	
  Due“,	
  
	
  	
  	
  	
  	
  	
  	
  tested.getTotalAuerTaxLong(1000));	
  
}	
  
	
  
Layout	
  tests	
  with	
  Robolectric	
  
@Test
public void checkPhoneNumberIsHidden() {
MyActivity activity = new MyActivity();
activity.onCreate();
TextView tv = (TextView)
activity.findViewById(R.id.callText);
assertEquals(View.GONE, tv.getVisibility());
}
Dead	
  End	
  -­‐	
  mid	
  by	
  bennylin0724,	
  CC	
  BY	
  2.0	
  
flickr.com/photos/benny_lin/191393604	
  
Test	
  all	
  the	
  Things!	
  
Start	
  your	
  engine	
  by	
  Norlando	
  Pobre,	
  CC	
  by	
  2.0,	
  flickr.com/photos/npobre/2601582256	
  
THANK	
  YOU	
  
Danny	
  Preussler	
  
GROUPON	
  	
  
Berlin	
  
	
  
dpreussler@groupon.com	
  	
  
github.com/groupon
engineering.groupon.com
Michael	
  Burton,	
  Roboguice	
  
Carlos	
  Sessa,	
  50	
  Android	
  hacks	
  
David	
  van	
  der	
  Bokke,	
  RoboRemote	
  
David	
  Willson,	
  Odo	
  
….	
  
Stephane	
  Nicolas,	
  RoboSpice	
  
Par)al	
  Supermen,	
  juliegomoll,	
  CC	
  by	
  2.0,	
  flickr.com/photos/juliegomoll/1352843346	
  

Unit testing on Android (Droidcon Dubai 2015)

  • 1.
    Unit  Tes)ng  on  Android   Danny  Preussler   GROUPON   DroidCon  Dubai   test  (c)  DaveBleasdale,  CC  by  2.0,  www.flickr.com/photos/sidelong/246816211  
  • 2.
    Groupon  is  the  global     leader  in  local  commerce,   making it easy for people around the world to search ! and discover great businesses at unbeatable prices. Source: Internal data,, March 2014 WORLDWIDE! 260M+ subscribers 53.9M active customers 500+ markets 900M+ deals sold 2 $5B+ in annual billings 12,000+ global employees
  • 3.
    Leading  the  way  in  mobile  commerce   Our mobile app is available in 43 countries. Groupon’s vibrant mobile marketplace connects! consumers with their local economy 3   Sources: Internal Data; iTunes ranking for US stores available here - https://itunes.apple.com/WebObjects/ MZStore.woa/wa/viewFeature?id=500873243&mt=8&v0=www-itunes25Bcountdown-appstore Nearly 110 million people worldwide have downloaded our mobile app at the end of Q4 2014. One of the 25 most downloaded free apps of all time More than 50% of our Global transactions were completed on a mobile device by the end of Q4 2014
  • 4.
    About Me? •  GrouponBerlin •  Groupon Merchant App •  Unit Test enthusiast
  • 5.
    What  people  say  about  unit  tes0ng   •  Slows  you  down   •  I  know  my  code   is  working!   •  Only  have  UI  Code   Day  27/365  -­‐  Imagina)on..  by  Caden  Crawford,  CC  by  2.0,  flickr.com/ photos/cadencrawford/8422302030  
  • 6.
    What is aUnit Test? •  Small   Opposite  of  an  end-­‐to-­‐end-­‐test   test  the  smallest  unit  possible   •  You  should  have  LOTS  of  them   •  Fast!!!!   er  by  www.GlynLowe.com,  CC  by  2.0,  flickr.com/photos/glynlowe/10921728045  
  • 7.
    Why  Unit  test?     •  Documents  behaviour     •  Refactoring  not  possible     without!     •  Gives  trust     •  Only  slows  down     if  you  don‘t  have  )me     for  quality  code  and  tes)ng  anyway   Day  27/365  -­‐  Imagina)on..  by  Caden  Crawford,  CC  by  2.0,     flickr.com/photos/cadencrawford/8422302030  
  • 8.
    Why  Unit  test?     Code  without  Test  =  Legacy  code     Only  Bad  Code  is  untestable!     Day  27/365  -­‐  Imagina)on..  by  Caden  Crawford,  CC  by  2.0,     flickr.com/photos/cadencrawford/8422302030  
  • 9.
    SOLID FOUNDATIONFlughafen Berlin-Brandenburg, Blickin die Abflughalle by Muns CC BY 3.0 http://commons.wikimedia.org/wiki/File:120513-BER-innen.JPG
  • 10.
    App development reality Tidygarage by Bryn Pinzgauer CC 2.0 http://www.flickr.com/photos/12394349@N06/4492572621/in/photostream/
  • 11.
    Pure JUnit? java.lang.RuntimeException: Stub! AndroidFirewall by Uncalno, CC BY 2.0 flickr.com/photos/uncalno/8538679708
  • 12.
    Robolectric New Android UnitTesting Lost  Horizons  -­‐  Light  by  Simon  &  His  Camera,  CC  by  2.0  flickr.com/ph
  • 13.
    New Android UnitTesting   •  still experimental •  hdp://tools.android.com/tech-­‐docs/unit-­‐tes)ng-­‐support   •  Project  structure:          src/main/java/Foo.java          src/test/java/FooTest.java •  gradle:   android { testOptions {     unitTests.returnDefaultValues = true } Lost  Horizons  -­‐  Light  by  Simon  &  His  Camera,  CC  by  2.0  flickr.com/photos/simon__syon/14842606832  
  • 14.
    What  to  test?   Start  your  engine  by  Norlando  Pobre,  CC  by  2.0,  flickr.com/photos/npobre/2601582256  
  • 15.
    Great Wall ofChina (IV) by isawnyu. CC 2.0 http:// www.flickr.com/photos/isawnyu/7183821643/in/photostream/ Separate Java and Android Code?
  • 16.
    Great Wall ofChina (IV) by isawnyu. CC 2.0 http:// www.flickr.com/photos/isawnyu/7183821643/in/photostream/ Separate Java and Android Code? Android is not Java+UI Intent, Bundle, SparseArray, Uri.. not fancy device classes! You will never reuse this on another Java platform, stop pretending! Context everywhere Recreate the System? (interface UI {...} ?)
  • 17.
    You  can  test  everything!   Typing  the  universe  by  Feliciano  Guimarães,  CC  by  2.0,  flickr.com/photos/jsome1/6097841770  
  • 18.
    „Mock“???   Martin Fowler: „test-doubles... pre-programmed with expectations “ Typing  the  universe  by  Feliciano  Guimarães,  CC  by  2.0,  flickr.com/photos/jsome1/6097841770  
  • 19.
    Typing  the  universe  by  Feliciano  Guimarães,  CC  by  2.0,  flickr.com/photos/jsome1/6097841770   Mock   TelephonyManager mgr = mock(TelephonyManager.class); when(mgr.getDeviceId()) .thenReturn("123456"); ...  
  • 20.
    Spy   MyPreferences pref= spy(new MyPreferences(context)); … verify(pref).saveTitle(same(title)); verify(pref).savePersonalData(anyString());     She  spy  by  Kangrex,  CC  by  2.0;  flickr.com/photos/kangrex/3012574701  
  • 21.
    Building blocks ofa Test   public class AndroidAccountsTest { AccountManager manager; AndroidAccounts tested;   @Before public void setup() {...} @Test public void should_get_token() { when(manager.peekAuthToken(....)).thenReturn("token"); String token = tested.getCurrentToken(...) assertEquals("token", token); } } swivel-­‐snot  by  Linus  Bohman,  CC  2.0,  flickr.com/photos/bohman/16062901379  
  • 22.
    Easy...   •  Test  u)lity  classes     •  Test  JSON  parsing     •  Test  API  layer     Duplo  Pac-­‐Man  by  Dan  Diemer,  CC  by  2.0,  flickr.com/photos/diemer/192740446  
  • 23.
    Gson gson =GsonFactory.getGson(); @Test public void should_parse_json_data() { String values = inputStreamToString(„auth.json")); AuthRslt rslt = gson.fromJson(values, AuthRslt.class); assertEquals("AQAAAABwgQ2vVzk-KjiEA3“, result.getAccessToken()); } Easy...   Duplo  Pac-­‐Man  by  Dan  Diemer,  CC  by  2.0,  flickr.com/photos/diemer/192740446  
  • 24.
    Easy  when  you  do  it  right   •  Test  user  interac)on  (click  etc)   •  Test  Fragments  and  Ac)vi)es     Lego  small  car.  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6805370739  
  • 25.
    class NavFragment extendsInjectedFragment { Interactor interactor; @OnClick(R.id.nav_button_checkout) public void onClickCheckout() { interactor.moveToCheckout( getActivity()); } } User  interac)on   Lego  small  car.  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6805370739   Test  for  this  is  trivial!  
  • 26.
    Screen  changes   @Test publicvoid should_do_transaction() { TransactionUtil transactionsUtil = mock(TransactionUtil.class), tested.showPaymentMethods( transactionsUtil, mock(Purchase.class)); verify(transactionsUtil) .addAllowingStateLoss( any(FragmentManager.class), eq(android.R.id.content), isA(PaymentFragment.class)); } Lego  small  car.  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6805370739  
  • 27.
    Screen  changes   Lego  small  car.  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6805370739   •  Robolectric  offers  FragmentTranscta)ons  and   life  cycle  method:   •  Robolectric .buildActivity( Activity.class) .attach() .create()..... •  Careful,  feature  flaky  
  • 28.
    Screen  changes   Lego  small  car.  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6805370739   •  Easier:   Field field = Fragment.class.getDeclaredField("mActivity"); field.setAccessible(true); field.set(fragmentInstance, mock(Activity.class); •  You  might  need  also  to  mock  getResources()
  • 29.
    Harder  but  possible   •  Test  UI  code     LEGO  10179  Ul)mate  Collector's  Millenium  Falcon™  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6966161598  
  • 30.
    Test  UI  code   public class BorderPainterTest { Canvas canvas = mock(Canvas.class); Circle circle = mock(Circle.class); BorderPainter tested = new BorderPainter(); @Test public void should_draw_two_circles() { ... tested.drawBorder(new RectF(), canvas, circle); InOrder inOrder = inOrder(canvas); inOrder.verify(canvas).drawCircle( anyFloat(), anyFloat(), eq(10f), any(Paint.class)); inOrder.verify(canvas).drawCircle( anyFloat(), anyFloat(), eq(20f), any(Paint.class)); } } LEGO  10179  Ul)mate  Collector's  Millenium  Falcon™  by  Do-­‐Hyun  Kim,  CC  by  2.0,  flickr.com/photos/s)ckkim/6966161598  
  • 31.
    Wri)ng  testable  code...   •  Clean  Code   •  Separa)on     of  Concerns   Manual  Inside  by  Masked  Builder,  CC  by  2.0,  flickr.com/photos/masked-­‐builder/8517238602  
  • 32.
    Dependency  Injec)on  helps   •  Don‘t  create  dependencies  yourself   •  Invert  Control!     •  Inject  them!   construct  by  Len  Madhews,  CC  by  2.0;  flickr.com/photos/mythoto/16412713709   Syringe  with  Green  Liquid  by  Andres  Rueda,  CC  by  2.0;  lickr.com/photos/andresrueda/16558374828  
  • 33.
    If  it‘s  hard  to  test...   •  Class  is  too  large   •  Class  is  doing  too  many  things   •  Class  knows  too  many  things   Modified  condi)on/decision  coverage  for  cri)cal  souware  tes)ng  by  Nguyen  Hung  Vu,  CC  by  2.0,  www.flickr.com/photos/vuhung/14621502361  
  • 34.
    Make  it  fail!   Apple  Mini  DisplayPort  adapter  FAIL  by  David  Joyce,   CC  by  2.0,  flickr.com/photos/deapeajay/2969264395  
  • 35.
    1  method  =  1  test?   •  Test  all  cases,  else  you  might  miss  sth   •  one  method  should  have  mul)ple  test     (although  coverage  already  reached  with  first)   •  Don‘t  be  super  strict  on  units,     some)mes  end  to  end  might  make  sense   i.e.  json  parsing  into  models  with  full  Json    
  • 36.
    Coverage?   • You  should  Measure     • Mo)vates!   • Don‘t  trust  too  much  into  it  
  • 37.
    When  to  use  Robolectric   •  Parcel  Tests   •  Arguments/Bundle  Tests   •  Resource  loading  Tests  
  • 38.
    Parcel  Tests  with  Robolectric   @RunWith(RobolectricTestRunner.class)   public  class  UserTest  {          Parcel  parcel  =  Parcel.obtain();          User  tested  =  new  User("123",  "456");            @Test          public  void  check_parcel_implementa)on()  {                  tested.writeToParcel(parcel,  0);                  parcel.setDataPosi)on(0);                  User  out  =  User.CREATOR.createFromParcel(parcel);                  assertEquals("123",  out.getUser());                  assertEquals("456",  out.getPassword());          }  
  • 39.
    Resource  Tests  with  Robolectric   @Test   @Config(qualifiers  =  "en")   public  void  getTotalAuerTaxLong()  {          assertEquals(      "$10.00  Due“,                tested.getTotalAuerTaxLong(1000));   }    
  • 40.
    Layout  tests  with  Robolectric   @Test public void checkPhoneNumberIsHidden() { MyActivity activity = new MyActivity(); activity.onCreate(); TextView tv = (TextView) activity.findViewById(R.id.callText); assertEquals(View.GONE, tv.getVisibility()); }
  • 41.
    Dead  End  -­‐  mid  by  bennylin0724,  CC  BY  2.0   flickr.com/photos/benny_lin/191393604  
  • 42.
    Test  all  the  Things!   Start  your  engine  by  Norlando  Pobre,  CC  by  2.0,  flickr.com/photos/npobre/2601582256  
  • 43.
    THANK  YOU   Danny  Preussler   GROUPON     Berlin     dpreussler@groupon.com    
  • 44.
    github.com/groupon engineering.groupon.com Michael  Burton,  Roboguice   Carlos  Sessa,  50  Android  hacks   David  van  der  Bokke,  RoboRemote   David  Willson,  Odo   ….   Stephane  Nicolas,  RoboSpice   Par)al  Supermen,  juliegomoll,  CC  by  2.0,  flickr.com/photos/juliegomoll/1352843346