Date post: | 16-Jul-2015 |
Category: |
Software |
Upload: | danny-preussler |
View: | 352 times |
Download: | 1 times |
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!!!!
container 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 Da
y 27/365 -‐ Im
agina)
on.. by Caden
Crawford, CC by 2.0,
flickr.c
om/pho
tos/cade
ncrawford/842
2302
030
Why Unit test?
Code without Test = Legacy code
Only Bad Code is untestable!
Day 27/365 -‐ Im
agina)
on.. by Caden
Crawford, CC by 2.0,
flickr.c
om/pho
tos/cade
ncrawford/842
2302
030
SOLID FOUNDATION
Flughafen 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/photos/simon__syon/14842606832
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-‐sno
t by Linu
s Boh
man, CC 2.0, flickr.com
/pho
tos/bo
hman/160
6290
1379
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 M
ini 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
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