How to build rock-solid apps and
keep 100m+ users happy
Iordanis Giannakakis
About me
• Iordanis “Jordan” Giannakakis
• Android Team Lead at Shazam
• @iordanis_g
@iordanis_g
How Shazam works
@iordanis_g
100+ million users
@iordanis_g
Happy users
@iordanis_g
Even developers?
Android testing
@iordanis_g
Faster release cycles
@iordanis_g
Better code
@iordanis_g
Cheaper
@iordanis_g
http://testdroid.com/testdroid/5851
Easy
@iordanis_g
A user walks into a bar...
@iordanis_g
Doing it the test-driven way
@iordanis_g
Write
UI test
Implement
Refactor
Write unit
test
BDD
TDD
“To TDD or not to TDD?
@iordanis_g
...That is not the question”
Seb Rose
http://claysnow.co.uk/to-tdd-or-not-to-tdd/
Test-first
@iordanis_g
• Generally easier
• Eliminates external dependencies
• Easily repeatable
The Acceptance tests cycle
@iordanis_g
Write
UI test
Implement
Refactor
Write unit
test
BDD
TDD
Acceptance criteria
@iordanis_g
Given: arrange
When: act
Then: assert
Example
@iordanis_g
Given a user is near a music venue
And the server always returns a known result
When the user Shazams
...
gwen
@iordanis_g
given(user).isNear(lexington())
given(server).returns(lustForLife())
when(user).shazams()
then(user).canC...
Acceptance tests technologies
@iordanis_g
• Instrumentation
• JUnit 3
• Robotium & Espresso
• gwen
• HamMock Server
The Unit tests cycle
@iordanis_g
Write
UI test
Implement
Refactor
Write unit
test
BDD
TDD
What we don’t test
@iordanis_g
Activities & Fragments
https://github.com/xxv/android-lifecycle/
What we don’t test
@iordanis_g
What we do unit test
@iordanis_g
• Presentation logic
• Business logic
• That’s all!
The MVP pattern
@iordanis_g
Presenter
Model View
The MVP pattern, for Android
@iordanis_g
Presenter
Model
View
start
stop
Android
The MVP pattern
@iordanis_g
• Makes presentation logic testable
• No need to test the “slave” view
• Avoid Android depende...
Dependency Injection, Yourself (DIY)
@iordanis_g
• Break hardcoded dependencies
• Behaviour vs implementation
• Swappable ...
Hard-coded dependencies
@iordanis_g
Client
Feature X Feature X
Dependency Injection
@iordanis_g
Client
Injector
Feature X
Interface
Model
@iordanis_g
public interface VenueRetriever {
void findClosestVenue(VenueFoundCallback callback);
}
public class Net...
Activity
@iordanis_g
public class ResultActivity extends Activity implements ResultView {
private final VenueRetriever ven...
Presenter
@iordanis_g
public class ResultPresenter {
public ResultPresenter(ResultView resultView, VenueRetriever
venueRet...
View
@iordanis_g
public interface ResultView {
void showResult(Result track);
void showCheckInPrompt(Venue venue);
}
Activity
@iordanis_g
public class ResultActivity extends Activity implements ResultView {
public void showResult(Result re...
Unit tests technologies
@iordanis_g
• JUnit 4
• Robolectric
java.lang.RuntimeException: Stub!
• Hamcrest
• JMock
Test execution
@iordanis_g
Continuous Integration
@iordanis_g
Speed (Hint: slow)
@iordanis_g
Usual execution
@iordanis_g
Test Suite
Spoon
@iordanis_g
http://square.github.io/spoon/
Fork
@iordanis_g
Test Suite
Fork
@iordanis_g
• Inspired by Spoon, but faster
• Infinitely scalable
• Current setup 1 test / 2 secs
• Pooled execution
Flakiness monitor
@iordanis_g
ADB Remote
@iordanis_g
https://github.com/sleekweasel/CgiAdbRemote
If all else fails...
@iordanis_g
If all else fails...
@iordanis_g
If all else fails...
@iordanis_g
Summary
@iordanis_g
• Testing is easier than you may think
• Practice, practice, practice
• Toolset is limited
• Ship it!
@iordanis_g
Questions?
Hiring...
Upcoming SlideShare
Loading in …5
×

How to build rock solid apps and keep 100m+ users happy

1,691 views

Published on

Published in: Engineering, Technology

How to build rock solid apps and keep 100m+ users happy

  1. 1. How to build rock-solid apps and keep 100m+ users happy Iordanis Giannakakis
  2. 2. About me • Iordanis “Jordan” Giannakakis • Android Team Lead at Shazam • @iordanis_g @iordanis_g
  3. 3. How Shazam works @iordanis_g
  4. 4. 100+ million users @iordanis_g
  5. 5. Happy users @iordanis_g Even developers?
  6. 6. Android testing @iordanis_g
  7. 7. Faster release cycles @iordanis_g
  8. 8. Better code @iordanis_g
  9. 9. Cheaper @iordanis_g http://testdroid.com/testdroid/5851
  10. 10. Easy @iordanis_g
  11. 11. A user walks into a bar... @iordanis_g
  12. 12. Doing it the test-driven way @iordanis_g Write UI test Implement Refactor Write unit test BDD TDD
  13. 13. “To TDD or not to TDD? @iordanis_g ...That is not the question” Seb Rose http://claysnow.co.uk/to-tdd-or-not-to-tdd/
  14. 14. Test-first @iordanis_g • Generally easier • Eliminates external dependencies • Easily repeatable
  15. 15. The Acceptance tests cycle @iordanis_g Write UI test Implement Refactor Write unit test BDD TDD
  16. 16. Acceptance criteria @iordanis_g Given: arrange When: act Then: assert
  17. 17. Example @iordanis_g 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
  18. 18. gwen @iordanis_g given(user).isNear(lexington()) given(server).returns(lustForLife()) when(user).shazams() then(user).canCheckIn(lustForLife(), lexington()) https://github.com/shazam/gwen
  19. 19. Acceptance tests technologies @iordanis_g • Instrumentation • JUnit 3 • Robotium & Espresso • gwen • HamMock Server
  20. 20. The Unit tests cycle @iordanis_g Write UI test Implement Refactor Write unit test BDD TDD
  21. 21. What we don’t test @iordanis_g Activities & Fragments https://github.com/xxv/android-lifecycle/
  22. 22. What we don’t test @iordanis_g
  23. 23. What we do unit test @iordanis_g • Presentation logic • Business logic • That’s all!
  24. 24. The MVP pattern @iordanis_g Presenter Model View
  25. 25. The MVP pattern, for Android @iordanis_g Presenter Model View start stop Android
  26. 26. The MVP pattern @iordanis_g • Makes presentation logic testable • No need to test the “slave” view • Avoid Android dependencies
  27. 27. Dependency Injection, Yourself (DIY) @iordanis_g • Break hardcoded dependencies • Behaviour vs implementation • Swappable dependencies for test and production runtimes
  28. 28. Hard-coded dependencies @iordanis_g Client Feature X Feature X
  29. 29. Dependency Injection @iordanis_g Client Injector Feature X Interface
  30. 30. Model @iordanis_g 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 look-up / caching layer, perhaps? } }
  31. 31. Activity @iordanis_g public class ResultActivity extends Activity implements ResultView { private final VenueRetriever venueRetriever; private ResultPresenter resultPresenter; public ResultActivity() { venueRetriever = venueRetriever(); } public void onCreate(Bundle savedInstanceState) { // TODO: Setup layouts & views Result result = resultToDisplay(); resultPresenter = new ResultPresenter(this, venueRetriever, result); } public void onStart() { resultPresenter.startPresenting(); } }
  32. 32. Presenter @iordanis_g 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); } }); } }
  33. 33. View @iordanis_g public interface ResultView { void showResult(Result track); void showCheckInPrompt(Venue venue); }
  34. 34. Activity @iordanis_g 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 check-in prompt view } }
  35. 35. Unit tests technologies @iordanis_g • JUnit 4 • Robolectric java.lang.RuntimeException: Stub! • Hamcrest • JMock
  36. 36. Test execution @iordanis_g
  37. 37. Continuous Integration @iordanis_g
  38. 38. Speed (Hint: slow) @iordanis_g
  39. 39. Usual execution @iordanis_g Test Suite
  40. 40. Spoon @iordanis_g http://square.github.io/spoon/
  41. 41. Fork @iordanis_g Test Suite
  42. 42. Fork @iordanis_g • Inspired by Spoon, but faster • Infinitely scalable • Current setup 1 test / 2 secs • Pooled execution
  43. 43. Flakiness monitor @iordanis_g
  44. 44. ADB Remote @iordanis_g https://github.com/sleekweasel/CgiAdbRemote
  45. 45. If all else fails... @iordanis_g
  46. 46. If all else fails... @iordanis_g
  47. 47. If all else fails... @iordanis_g
  48. 48. Summary @iordanis_g • Testing is easier than you may think • Practice, practice, practice • Toolset is limited • Ship it!
  49. 49. @iordanis_g Questions? Hiring...

×