Saturday, February 18, 2017

Testing Where

Testing testing testing.
Everybody always wants to have tests.
Would it surprise you to know that I have almost no tests? Of course it wouldn't.
But lets talk a bit about where we should seek to test and why.

In a basic Android MVP project, you can split your code up into mainly three larger layers:

The View

The Presenter

The Model

The View is dumb. While some people do like to write unit or integration tests for it, generally you should hope you don't have to. What's more important for the View layer is that it feels right, and that interaction with the application through various screens and flows doesn't do anything unexpected. It's probably the most dog food layer for testing. Generally you would just be dealing with direct implementations, Activities and Fragments and Views.

The Presenter is dumb as well. The presenter should serve a single, easy purpose. It should parse information from your Model layer and package it into easy bite sized pieces for the View layer to react to. It shouldn't need extensive testing because, well, it shouldn't do any heavy lifting. While we don't want to call this layer dumb, it should have so little logic in it that there is really nothing important to test. To make my point, many of my applications have a presenter which simply subscribes to an Observable and puts the RX operations on the correct scheduler. While some people like to make this layer accessible via Interfaces and then hide an implementation (as I used to do) it adds a large amount of extra files for no real benefits. You should be safe working with direct implementations here too.

A sublayer of the Presenter layer is the optional Interactor that many programmers use to define an interface which interacts with raw sources of data and parses it into something that can be consumed by the Presenter object. I use Interactors in my projects as well and enjoy the idea of a middle man object like a DAO. While the data they consume is ever changing, I like to fall back on the Observable object as the resulting something that I pass to my Presenters. The Interactor does some heavier lifting, it's job would be to take various sources of data and turn them into objects that are consumable by the Presenter, so there may actually be a lot of logic here. As such, you'd probably prefer to work with direct implementations instead of interfaces, because you want to know that your logic for parsing these raw types into consumable Objects is correct. You don't want to have a test double for your underlying logic.

Where you want to actually be able to drop in test doubles is in your Model. If you are able to double the data source and data stores, then you shouldn't care about testing the other layers. You would simply need to validate that your Interactor, Presenter, and View all perform the way you would expect given a set model. By making sure that various fake double models are handled correctly, you have validated that your logic is sound between the other layers of your application.

The real model is anything that you would consider a data source or data store. Databases, shared preferences, files, Android specific device components (like the Camera) should all be abstracted away behind a POJO interface where possible. Even things like your Retrofit interface which defines your endpoints, and your Autovalue classes would fall in this category. By being able to provide test doubles for a database operation, or shared preference storage, or even the response to a Camera request, you can validate that your logic in the application is sound. Because it is out of your control to handle things like the underlying Camera API or how Retrofit hit endpoints, you can rest assured that if your tests pass, its as good as things will get.

You can reduce the number of tests and interface doubles in your code to strictly the classes that are in the Model layer. This should help clean up your code and allow you to remove many redundant tests which may be duplicating or even replacing your production logic for Interactors, Presenters, and Views.

Or you can be like me and have no tests at all.

:)

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================