How to Build a fuel logger “Android App” Guided by Tests

Photo by Robert Tudor on Unsplash

I’m a great fan growing object oriented code guided by test. Therefore, I created a small application demonstrating domain modelling skill and test driven development.

Before I begin, I do have five book recommendations on how to modelling the domain and last two for unit testing:

  1. Practical Object Oriented Design in Ruby by Sandi Metz
  2. Domain Driven Design Quickly by Abel Avram and with Floyd Marinescu as managing editor.
  3. Growing Object Oriented Code Guided by Test by by Freeman and Price
  4. Art of Unit testing by Roy Osherove
  5. Working effectively with legacy code by Michael Feathers

Below is the rough requirement for the app to be used:

Should track fill-ups, mileage, and fuel consumption.

Just enter fuel per unit price, amount and odometer while you are at the pump.

The application will show you distance and average fuel consumption.

Tools Used:

  • Gradle as build tool
  • Android Studio as IDE
  • Java as programming language
  • CircleCI as CI

Testing Frameworks:

  • Robolectric
  • Espresso
  • Mockito

Coding Coverage

  • Jacoco
  • CodeCov

Code Quality Measure

  • Codacy

Requirement Breakdown

The idea of the fuel logger is to create a offline Android app using java where the user can:

  • Can view metrics like Average consumption, Driving cost and Total Kms, Total amount costs, Total Fuel consumption upon opening application
  • Can add a fuel log with mandatory fields like date, current odometer, fuel unit price, amount filling
  • ̶C̶a̶n̶ ̶e̶d̶i̶t̶/̶d̶e̶l̶e̶t̶e̶ ̶a̶n̶y̶ ̶e̶n̶t̶r̶y̶ (not covering as part of this)
  • Can see full log entries.

Start

I did tests on the FreeBSD operating systems. You can download the project:

git clone https://github.com/Manikkumar1988/FuelLogger.git

Now, you can run unit test

./gradlew​ ​test

Above command executes (shared) instrumented tests + unit tests on JVM.

Additionally, you can run UI (or Instrumented) test on device or emulator

./gradlew cAT

Above command executes (non-shared + shared) instrumented tests tests on Device/Emulator.

You can see more details of the implementation by looking at the project’s git homepage.

Intro to Instrumented test:

First things first, as you start writing the unit testing for UI, question that will raise in our mind is how to mock the dependency of viewmodel within Fragments.

That being said, To get to into this level all your business logic should have been moved to viewmodel, your fragments or activity should be dumb enough to just bind the data or manipulate UI attributes (example visibility, enabled) based on data.

Injection of mocked class(Mostly ViewModelFactory in my case) into Fragments

Complete Example:

As mentioned earlier, One great thing after Google IO 2018, you can now execute above test code on and off device/emulator without any code change, more about it here.

Object Modelling

Class Diagram

FuelLogs Composite of FuelLog, responsible for calculating stats on collection of FuelLog entities like average consumption, total distance, total fuel consumption, total amount since inception.

FuelLog An “Entity Object” having timestamp as identity and other attributes that makes sense to problem statement.

FuelDao The Data Access Object (DAO) to isolate the application/business layer from the persistence layer (usually a relational database, but it could be any other persistence mechanism) using an abstract API.

Let’s examine which of these are a more natural way of expressing our intent.

FuelLogs has a List of FuelLog objects or,

FuelLogs is a List of FuelLog objects.

In real world, driver would be having a book, having all entries entered in row wise. Similarly FuelLogs is equivalent to book, so we can conclude that FuelLogs has a list of FuelLog objects hence composite relation.

Also FuelLogs has one to many relationship with FuelLog.

Application Architecture

MVVM

  1. Passing​ ​Event​ ​Triggered​ ​from​ ​View​ ​to​ ​ViewModel
  2. Passing​ ​Event​ ​Triggered​ ​from​ ​background​ ​Operation​ ​to​ ​View
  3. Passing​ ​Event​ ​from​ ​Fragment​ ​to​ ​Activity​ ​or​ ​Vice​ ​Versa

are​ ​performed​ ​view​ ​ObservableList​ ​or​ ​MutableLiveData​ ​which​ ​are​ ​​ observable​ ​pattern.

And in the fragment/activity, need to observe for the event as below

Considerations

Few extension I would like to see is support for multiple vehicle, better way of calculation stats without loading full data, supporting multiple metrics, ability to skip the entry for stats computation.

This project is only used for studies using android developed by layman in the subject, and perhaps not one of the best implementations, techniques, and uses of the language.

I am always open to feedback, so free feel to let me know what you think in the comments below.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store