A presentation at QCon London 2015 in March 2015 in London, UK by Savvas Dalkitsis
How to build rock-solid apps &"keep"100m+"users"happy" Iordanis)Giannakakis)) iordanis_g " Savvas ) Dalkitsis )) @ geeky_android "
qconlondon "
How Shazam works
Some numbers
Happy users Even developers?
Android testing
Faster release cycles
Better code
Cheaper http://testdroid.com/testdroid/5851
Easy
A user walks into a bar
Doing it the test driven way "" "" Write"UI" test" Implement" Refactor " Write"unit"test" BDD" TDD"
Test first • Generally easier • Eliminates external dependencies • Easily repeatable
The Acceptance Tests cycle "" "" Write"UI" test" Implement" Refactor " Write"unit"test" BDD" TDD"
Acceptance criteria • Given: arrange • When: act • Then: assert
Example Given a user is near a music venue And the server always returns a known result
When the user Shazams
Then the user can check-in their discovery
gwen
!given(user). isNear ( lexington ());! !given(server).returns( lustForLife ());! !! !when(user). shazams ();! ! !then(user). canCheckIn ( lustForLife (),! lexington ());! http://github.com/shazam/gwen
Other libraries for Acceptance Tests • Instrumentation • JUnit 3 • Espresso & Robotium
• Fork • HamMock Server
The Unit tests cycle "" "" Write" UI"test" Implement" Refactor " Write"unit" test" BDD" TDD"
What we don’t test Activities & Fragments http://github.com/xxv/android-lifecycle
What we don’t test
What we do test
• Presentation logic • Business logic • That’s it
The MVP pattern
Presenter Model View
Presenter Model View Android
• Makes presentation logic testable • No need to test “dummy” view • Avoid Android dependencies
Dependency Injection, Yourself
• Breaks hardcoded dependencies • Behaviour
vs Implementation • Implementations for test & runtime
Feature X Hardcoded dependencies
Client Feature X
Dependency Injection
Client Feature X Interface Injector"
Model !public ! interface ! VenueRetriever !{! !!!! void ! findClosestVenue ( VenueFoundCallback ! callback );! !}! ! !public ! class ! NetworkVenueRetriever ! implements! VenueRetriever !{ ! !!!!public ! void ! findClosestVenue ( VenueFoundCallback ! callback )!{! !!!!!!!//!Some!slow!networking! !!!!}! !}! ! !public ! class ! LocalVenueRetriever ! implements! VenueRetriever !{ ! !!!!public ! void ! findClosestVenue ( VenueFoundCallback ! callback )!{! !!!!!!!//!DB!lookJup!/!caching!layer,!perhaps?! !!!!}! !} "
new ! ResultPresenter ( this ,! venueRetriever ,!result);! !!}! ! !! public ! void ! onStart ()!{! !!!! resultPresenter .startPresenting ();! !!}! } "
Presenter !public ! class ! ResultPresenter !{! ! !!!! public ! ResultPresenter ( ResultView ! resultView ,! VenueRetriever !! !!!!!!!!!! venueRetriever ,!Result!result)!{! !!!!!!! this . resultView !=! resultView ;! !!!!!!! this . venueRetriever !=! venueRetriever ;! !!!!!!! this . result !=!result;! !!!!}! ! !!!! public ! void ! startPresenting ()!{! !!!!!!! resultView .showResult ( result );! !!!!!!! venueRetriever .findClosestVenue ( new ! VenueFoundCallback ()!{! !!!!!!!!!! public ! void ! venueFound (Venue!venue)!{! !!!!!!!!!!!!! resultView .showCheckInPrompt (venue);! !!!!!!!!!!}! !!!!!!!});! !!!!}! !} "
View !public ! interface ! ResultView !{! ! !!!! void ! showResult (Result!track);! ! !!!! void ! showCheckInPrompt (Venue!venue);! !}!
Activity !public ! class ! ResultActivity ! extends !Activity! implements ! ResultView !{! ! !!!! public ! void ! showResult (Result!result)!{! !!!!!!!// TODO !show!the!result!screen!&!bind!result!data! !!!!}! ! !!!! public ! void ! showCheckInPrompt (Venue!venue)!{! !!!!!!!// TODO !bind!the!venue!with!checkJin!prompt!view! !!!!}! !} "
Other Unit Test technologies • JUnit 4 • Robolectric
java.lang.RuntimeException : Stub!
• Hamcrest
• JMock
Test execution
Continuous Integration
Speed (Hint: slow)
Usual execution Test"Suite"
Spoon http://github.com/square/spoon
Fork http://github.com/shazam/fork
Test"Suite"
Example
• Pooled execution • Infinitely scalable • Current setup 1 test / 2 seconds
Flakiness monitor
ADB Remote http://github.com/sleekweasel/CgiAdbRemote
If all else fails
Summary • Testing is easier than you may think • Practice, practice, practice • Toolset is limited but getting better • Ship it!
Questions?