/qualitymatters

Android Development Culture

Primary LanguageJavaApache License 2.0Apache-2.0

QualityMatters

This is the app that follows all principles of Android Development Culture Document.

What does it have:

  • CI (Travis) - Build Status
  • Unit tests (some under Robolectric, some are under plain JUnit runner with mocked android.jar).
  • Integration tests to see that Http, REST, JSON parsing and RxJava work well in composition.
  • Functional (UI) tests (Espresso with custom rules, mocked server and Screen-architecture) to check that app works according to the expectations from the user's point of view.
  • Static code analysis (FindBugs, PMD, Android Lint, Checkstyle) (see root build.gradle).
  • Code coverage codecov.io
  • Developer Settings Menu where you can enable/disable Stetho, LeakCanary, etc. See full list below (feel free to add more tools!).
  • Git sha & build time without breaking incremental compilation! (Thanks to Paperwork)
  • MVP, RxJava, Dagger 2, Retrofit 2 and so on.

Made with ❤️ by Artem Zinnatullin https://twitter.com/artem_zin.

To build the project run sh ci.sh (yep, that easy, because it should be easy).

Screenshots:

###Tests

####Unit tests

App has unit tests and they live mostly in src/unitTests., but app also has debug and release specific code, so there are also debugUnitTests and releaseUnitTests.

Unit tests check classes/methods in isolation from others, all dependencies are mocked.

All unit tests run on the JVM, no emulator or device is required. Mostly, unit tests run with mocked android.jar (it's a builtin feature of Android Gradle Plugin) but some of tests need things like Intent, etc and such tests run under Robolectric.

Also, you might notice that app has custom unit test runner. It's required to override and mock some dependencies under Robolectric, like Analytics, who needs real Analytics in Unit tests?

####Integration tests

App has integration tests and they live in src/integrationTests.

Integration tests check composition of multiple classes, for example OkHttp + Retrofit + Jackson + RxJava == API level, mostly all classes are real and not mocked, but for instance, we mock web server in integration tests.

All integration tests run on the JVM under Robolectric.

Also, you might notice that app has custom integration test runner. It's required to override and mock some dependencies, like Analytics, who needs real Analytics in integration tests?

####Functional (UI) tests

App has functional (UI) tests and they live in src/functionalTests.

Functional tests check how the product (Android app) works from the point of User's view, so basically, functional test of Android app check UI of the app and different use cases.

All functional tests run on connected emulator/device via Instrumentation API.

Also, you might notice that app has custom functional test runner (yep). It's required to override and change implementation of some dependencies, like Analytics, instead of posting tons of useless data to Analytics during functional tests we simply output it to the LogCat!

###Developer Settings

Tools:

  • Stetho — inspect the app via Chromium Developer Tools (network requests, db, preferences and so on). Must have for developers.
  • LeakCanary — detect memory leaks without IDE! Must have for QAs and developers.
  • TinyDancer — see frame rate right on your screen. Must have for QAs and developers.
  • Lynx — see LogCat output right in the app, useful for QAs and developers.

Details of implementation

Developer Settings presented only in debug build type, libraries and resources used for Developer Settings compiled only into debug build and main source set knows only little abstractions over Developer Settings just to initialize real implementation in the debug build code. In release build type DeveloperSettingsModule (Dagger) just returns no-op implementation of DeveloperSettingsModel.

Why only debug builds? The Answer is simple — dex limit. LeakCanary brings about 3k of methods, Stetho brings about 2k and so on. The more tools you add to Developer Settings — the bigger apk you receive. Situation is even worse if your main code is near to 65k methods. In our production app we had to turn on multidex for debug builds.

###Packages structure

Many people ask why app has component-based structure of the packages: presenters, models, etc. instead of feature-based structure: itemslist, developersettings, etc.

With component-based structure of packages new persons on the project (like those who read the code of this app) can easily find what presenters does the app have, what views, models and so on. If you read the code and you want to quickly move to some class related to current one you can simply press t right on the GitHub and search for the required file!