Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

1,706 views

Published on

Shazam is a very popular audio recognition app. It is installed on 100M+ Android devices and it’s growing rapidly. In this talk, we will address how we made the release schedule faster, more predictable and with more features by using BDD and automation testing.

We’ll demonstrate how that can be done without slowing down or hindering the development process and why our developers actually find writing tests is fun. Finally, we’ll look at how our testing strategy has translated to our testing framework and hardware infrastructure.

Published in: Engineering
  • Be the first to comment

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

  1. 1. How Shazam works
  2. 2. 100+ million users
  3. 3. Happy users Even developers?
  4. 4. Android testing
  5. 5. Faster release cycles
  6. 6. Better code
  7. 7. Cheaper http://testdroid.com/testdroid/5851
  8. 8. Easy
  9. 9. A user walks into a bar
  10. 10. Doing it the test driven way Write UI test Implement Refactor Write unit test BDD TDD
  11. 11. Test first • Generally easier • Eliminates external dependencies • Easily repeatable
  12. 12. The Acceptance Tests cycle Write UI test Implement Refactor Write unit test BDD TDD
  13. 13. Acceptance criteria • Given: arrange • When: act • Then: assert
  14. 14. 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
  15. 15. gwen given(user).isNear(lexington()); given(server).returns(lustForLife()); when(user).shazams(); then(user).canCheckIn(lustForLife(), lexington()); http://github.com/shazam/gwen
  16. 16. Other libraries for Acceptance Tests • Instrumentation • JUnit 3 • Espresso & Robotium • Fork • HamMock Server
  17. 17. The Unit tests cycle Write UI test Implement Write unit Refactor test BDD TDD
  18. 18. What we don’t test Activities & Fragments http://github.com/xxv/android-lifecycle
  19. 19. What we don’t test
  20. 20. What we do test • Presentation logic • Business logic • That’s it
  21. 21. The MVP pattern Presenter Model View
  22. 22. The MVP pattern Presenter Model View Android
  23. 23. The MVP pattern • Makes presentation logic testable • No need to test “dummy” view • Avoid Android dependencies
  24. 24. Dependency Injection, Yourself • Breaks hardcoded dependencies • Behaviour vs Implementation • Implementations for test & runtime
  25. 25. Hardcoded dependencies Feature X Client Feature X
  26. 26. Dependency Injection Client Feature X Interface Injector
  27. 27. 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 look-­‐up / caching layer, perhaps? } }
  28. 28. Activity 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(); } }
  29. 29. Presenter public class ResultPresenter { ResultPresenter(ResultView resultView, VenueRetriever venueRetriever, Result result) { public 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); } }); } }
  30. 30. View public interface ResultView { void showResult(Result track); void showCheckInPrompt(Venue venue); }
  31. 31. 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 check-­‐in prompt view } }
  32. 32. Other Unit Test technologies • JUnit 4 • Robolectric java.lang.RuntimeException: Stub! • Hamcrest • JMock
  33. 33. Test execution
  34. 34. Continuous Integration
  35. 35. Speed (Hint: slow)
  36. 36. Usual execution Test Suite
  37. 37. Spoon http://github.com/square/spoon
  38. 38. Fork Test Suite http://github.com/shazam/fork
  39. 39. Example
  40. 40. Fork http://github.com/shazam/fork
  41. 41. Fork • Pooled execution • Infinitely scalable • Current setup 1 test / 2 seconds http://github.com/shazam/fork
  42. 42. Flakiness monitor
  43. 43. ADB Remote http://github.com/sleekweasel/CgiAdbRemote
  44. 44. If all else fails
  45. 45. If all else fails
  46. 46. If all else fails
  47. 47. Summary • Testing is easier than you may think • Practice, practice, practice • Toolset is limited but getting better • Ship it!
  48. 48. Questions?

×