Category Archives: Testing

Rebuilding a legacy app from the scratch (II): Adding Continuous Integration with Travis CI

Continuous Integration (CI) is a Software engineering practice where developers in a team continuously integrate their work in the main stream of source code at least once a day.

Why?

The main goal of the CI practice is to reduce the integration problems that quite often happen when we have a team of several people working in different features and parts of our system. The sooner we integrate our code the easier is to identify problems like dependencies between modules, compilation issues, regression, duplication in code, etc, etc.

How?

Continuous Integration is overall an attitude and good Software practice. In order to achieve it we need some tools and organisation.

First of all we need our source code in a repository, in our case to maintain MadridBus app we are using Github in a public repository.

Next we need a platform to perform the automatic builds of our code every time we push code to the repository. For our app we are going to use Travis CI. Travis is a hosted distributed CI platform, it’s free for public repositories and it’s quite easy to integrate and configure in our project.

Finally we need a good suite of Unit Test that are going to run every time a new build is launched, that as we mentioned before is going to happen for each push that we make in our repo. We will talk about the testing strategy in further posts but in the mean time you can take a look to one of my previous posts.

TRAVIS CI configuration

So first thing is going to https://travis-ci.org/ and we sign in with the Github account travisci-mascot-1-bc6a3179f3e8e1ab1456634bd55a448awhere we have allocated the Android project.

Then we are going to select the project we want to set up with continuous integration and that’s pretty much it, we can start building!

But not so fast, probably your build is going to fail as we need to set it up properly for Android projects, and the way to do this is adding the “.travis.yml” configuration file.

Below you can see the current MadridBus Travis configuration file:

language: android

jdk: oraclejdk8

cache: false

sudo: true

env:
  global:
    - ANDROID_API_LEVEL=25
    - ANDROID_BUILD_TOOLS_VERSION=25.0.0
    - ANDROID_ABI=armeabi-v7a
    - ADB_INSTALL_TIMEOUT=20 # minutes (2 minutes by default - see #247)

android:
  components:
    - platform-tools
    - tools
    - build-tools-$ANDROID_BUILD_TOOLS_VERSION
    - android-$ANDROID_API_LEVEL
    # Google Play Services
    - extra-google-google_play_services
    # Support library
    - extra-android-support
    # Latest artifacts in local repository
    - extra-google-m2repository
    - extra-android-m2repository
    # Specify at least one system image
    - sys-img-armeabi-v7a-android-$ANDROID_API_LEVEL

# Emulator Management: Create, Start and Wait
before_script:
  - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a
  - emulator -avd test -no-skin -no-audio -no-window &
  - android-wait-for-emulator
  - adb shell input keyevent 82 &

script:
  - android list target
  - ./gradlew connectedAndroidTest

licenses:
    - 'android-sdk-preview-license-.+'
    - 'android-sdk-license-.+'
    - 'google-gdk-license-.+'

Right, so let’s take a look to the interesting parts. As you can see in the first two lines we are specifying the project type with “language: android” and the JDK version 8 to be used to compile with “jdk: oraclejdk8”.

Right now by default Travis will build our project with Android SDK 24, so if we want to install and build with a latest SDK and use any other additional component we need to specify it as we can see it in the section “components” under the “android” tag.

As you can see in the example we are indicating that we want to use Build Tools version 25.0.0, Android SDK 25 and also that we are using Google Play Services adding “extra-google-google_play_services”. One important thing here is to tell Travis to accept all the licences when installing additional components, otherwise the build will fail. For this we are adding the section “licenses” as you can see above.

Finally we want to launch an emulator so we can run the tests. To accomplish this we are adding the section “before_script” where we are launching and waiting until is running for the emulator with the image type as configured in the field “sys-img-armeabi-v7a-android-$ANDROID_API_LEVEL”.

And that’s it! We just need to push new code to the repository and Travis will build automatically the project and run the tests for us.

In next posts we will see how to add our testing strategy including Unit Tests with JUnit, Integration Tests with Espresso, mocking with Mockito, etc.
Stay tunned!

Advertisements
Tagged , , ,

Rebuilding a legacy app from scratch: MadridBus revamp (I)

MadridBus was the second application that we released in Quoders to the app store. It is an adaptation from the original BilbaoBus, an app to get public transport information like routes, stops info, timetable, etc. It was born just as a learning side project but we got good traction from the beginning  and it grew up having more public transport agencies, improved UI, etc.

screen-shot-2016-10-01-at-09-27-38On the other hand MadridBus wasn’t so popular, probably because there were already a few decent applications in the market for the city of Madrid, so we didn’t focus so much on it. As a result, now days the app looks and feel really outdated, the UI is clunky and the plumbing of the app are really ugly and not maintainable.

So for this reason I have decided to rebuild the app from the scratch as one of my side projects. It will be open source published in Github. I will be explaining here in the blog all the design and implementation decisions, the different techniques, libraries, etc. The goal, apart from having a new and better application, is to have a project that could be a reference for new Android developers and hopefully help them to have a better understanding in how to implement from zero an Android app following good practices, patterns and explain the usage of Android concepts and most used libraries.

In this post I am going to give a quick summary of the different features, patterns, design and other elements that I am going to use following the best practices and modern Android development techniques. In following post I will be describing in more detail each of these elements and explaining the implementation and the source code will be available on Github.

Minimum Viable Product scope and features

So first thing first, let’s define the MVP (Minimum Viable Product) features and requisites.

The current published version of MadridBus has five main features:

    • Go To: This feature allows the user to search a route between point A to B, either pointing in the map or searching by address. This functionality, despite being really useful when you don’t know the city or the best route, interestingly it’s not very used as our Google Analytics data reveals.
    • Line List: Display the list of all the lines (day and night) available and allows the user to see the stops for a specific line and then the next bus time.
    • Stops List: Display a list of all the bus stops in the network. This functionality again is not really very useful, unless you know the name of the stop and want to look up.
    • Favourites: This is really useful as the user can save here to have quick access to the favourites stops, like work, home, etc.
    • News: Display a list of news fro the rss service of the bus agency. Useful when there are disruptions, changes, etc.

So for the MVP of the new app, taking into account what features the users are really using in the published app,  I’m going to go for the Line List, Favourites and News. Also we will be releasing an Android Wear app that will displayFor the V2, we will be adding the Go To feature and maybe the Stops list.

App architecture: Data access and storage

A public transport application needs to work with an extensive and complex source of data containing lines information, time tables, real time, geolocation, etc.

For MadridBus we are going to need two different set of data that we will retrieve from the Madrid public transport agency web servers:

The first one are static data that needs to be downloaded periodically and stored in the device for quick access offline.  This set of data contains the bus lines info, route s, stops position, etc.

The second type of data are the real time information, this will be accessed when we needs to display the real time info of the next bus for a specific stop.

To accomplish this network access we are going to use the well known library Retrofit from Square.  There are other options like Volley from Google but in my personal opinion and as you can see in some reviews like this, Retrofit is much better option. For more information you can check my blog post about Retrofit.

For the data storage on the device we are going to use a local data base managed with the library Realm. Databases in Android usually is a pain to implement using the SQLite API, but with real we simplify and make more robust and less error prone our data base implementation. It supports multithreading, encryption, reactive extensions, etc.

UI Layer: Material design

So now let’s talk about the UI layer. As we mentioned before, for the version 1 we are going to implement just the Line list, Favourites and News functionalities.

We can see clearly three different features that will need three direct access from the home screen. So following the Material Design guidelines we are going to use the recently added Bottom Navigation widget that will give us access to the three different features of the app. As we can see in the documentation,  this component is recommended for between three and five sections. In case we needed more is recommended to use a Tab view component or maybe using the left navigation drawer.

So the first option is the Home view and it will display a Google Maps showing the location of the user and the nearest bus stops. The second option will be the Line List, using a Recycler view to display the lines info, and the third option will be News screen, again using a Recycler view. We will post designs and wireframes in a future post when we start implementing this.

UI Layer: The MVP pattern

The MVP is now days one of the most used patterns in the Android community  when it comes to organise the UI layer. There are multiple benefits like much more modular, reusable and testable code. For a complete description and explanation of the pattern take a look to one of my previous blog post.

As a quick summary, the Activities, Fragments and custom views will be the View layer of the pattern and they will contain only pure UI functionalities.

The Presenter will be a man in the middle layer that will work as intermediary between the Views and the Model. They will respond to events and actions from the user on the View and it will perform any action required using the Model layer.

Modules wiring and communication

So as we are going to have different layers in the app following we need some mechanism to communicate with each other, passing data, etc.

There are different ways to accomplish this, we have just the traditional way using listeners, but we agree that this comes with many problems and we end up with the infamous hell of listeners.

Another better solution would be using an event bus, but this again has its own downside. The code end up being less readable it grows up having multiple events dispatching from everywhere with unexpected results.

There is a better solution and will be using RxJava. As we know it’s one of the library and techniques that has focused the attention of the Android community for a while now.

We will see in a future post and in the code of the app how to use RxJava and how to architect the app using it and all the benefits that it has. In the mean time you can have a look to my blog post about it.

Testing and Continuous Integration

Testing is often one of the most neglected aspects of the applications development process. For our application we are going to implement two main type of test: Integration Test using Espresso (UI test) and Unit Test when relevant with JUnit.

For more information about a good testing strategy take a look to my blog post about it.

Continuous Integration is another key piece of our app development as it allows us to have a build of our app everytime we submit changes to the code repository. This way we can launch our tests suite every time we make a change in the code validating it’s correctness.

For this functionality we are going to use Travis, a CI platform totally free for open source projects. Once again we will be explaining the configuration in next posts.

Summary

So that’s it for today, as mentioned before we are going to be publishing blog posts to comment and explain the implementation of the different parts of the new app as we progress coding it.

Stay tuned!

A beginners guide to an effective Android testing strategy

Testing quite often is one of the most neglected aspect in many Software projects, and in Android this has been particulary a common issue since the beginning of the platform.
atsl-logo

Even Google didn’t seem to be making big efforts to encourage testing: Documentation was almost nonexistent, the tools and frameworks were confusing or hard to use and there was almost impossible to find an open source project with good testing implementation.

 

Why testing?

Implement a good suite of different type of tests with a good coverage ratio and maintain it requires time and discipline from the dev team. In some cases the member of the team might not be familiar with the testing frameworks or even never have implemented any  type of test. So what are the benefits of this time and resource investment? Here some of the reasons:

  • Testing allows us to check the correctness of the app features. We should never rely on the QA team to find defects in our code. Is a very common practice to implement some feature, test a couple of use cases, send it to the quality team and wait until they find a few bugs for us and then fix it. This is really a bad practice that a professional developer should never do. We should be confident that the deliverables that we release to QA team shoulders been tested throughly, has a good test code coverage and that our quality colleagues should almost never find a bug.
  • Improves the design and modularity of our code base. If we create a new feature with a TDD approach, we will be building our classes in short iterations, thinking in the interface and driving the implementation with the proper user requirements in mind. This will make our modules and classes small, independent and with one only responsibility unit.download
  • Help us to implement new features or refactor existing one with much more confidence that our changes will not break current working and tested
    functionalities. If every time we add a new piece of code to our project we run our test and all pass, we can be sure that we didn’t implement anything that is affecting and having negative side effects on the existing features.

 

Types of test

In the Android platform, generally we will implement two categories of tests: Unit Tests and Integration Tests.

  • Unit Tests.  We will test small and independent pieces of code. It might be a single class, an interface or just a method. We can consider it as the smallest possible testable piece of code part of an specific independent module. In Android we will use JUnit running either locally on the JVM (prefer this one as fastest method) or in an emulator or real device.
  • Integration Tests. We are testing more than one individual module working together that implements a complete functional part of our system. For example we test the Login feature of our application where different entities works together and and we want to test that the login process is accomplished successfully on different scenarios. In this case in Android  we will implement UI Instrumentation tests with Espresso and Automation tests with UI Automator.

 

Architecting the app for testing

As we mentioned before one of the complains of the Android community was that testing the platform was a difficult task. Apart from the lack of a good testing framework, the developers faced the problems of implementing tests for modules (Activities, Fragments, etc) coupled to multiple Android SDK dependencies.

In order to mitigate this issue, one best and most common solutions is to architect our application using the MVP pattern. With this approach we manage to have a clear separation of concerns of our modules making much more easy to unit test our models and use cases classes without having to mock and get around of all the Android SDK dependencies.

Typically we will have our View layer with the Activity or Fragment that have almost no logic at all. A Presenter acting as a bridge and a Model which will have our use cases and where we will probably focus most of our unit tests.

In a previous I made a basic introduction of the MVP pattern where you can see all these concepts with more detail.

Test Pyramid

Following the TestPyramid concept described by Mike Cohn, Unit Tests should be around test_pyramid60-70% of our test code base and the rest 30% should be implemented as End-to-End tests (Integration, functional, UI tests).

The reason for this is that the end to end tests has a few problems, like you need to wait until the app is deployed and running in a device. Then probably the test will have to deal with things like login, registrations, database access, etc.
Also if you find a bug it will be hard to figure out where exactly the problem is, as it could be in any of the multiple modules and components that are involved in the specific user flow.

On the other hand Unit Tests are fast, reliable and they isolate the test scope to very specific and isolated pieces of the system which makes it a much better way to identify the defects in our system.
If we have build our code base using TDD, we will probably have test covered almost all modules of our application which will give us peace of mind that all parts of the application are being tested and any regression would be detected.

Implementing Unit Tests

First let’s add to the project build.gradle file the required dependencies for Espresso, JUnit, UIAutomator, etc.

    // Dependencies for unit testing
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-all:1.10.19'
    testCompile 'org.hamcrest:hamcrest-all:1.3'

    // Android Testing Support Library's runner and rules
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile 'com.android.support.test:rules:0.3'

    // Espresso UI Testing
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2'
    androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2'

    // UIAutomator Testing
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
    compile 'javax.inject:javax.inject:1'

As we mention before we have two options to run Unit Tests, one is locally on the JVM and the other is running with UI Instrumentation runner. We will favour the local JVM test as they will compile and run much faster. The downside is that these can’t have any Android SDK dependency, but that should be our goal as we saw before using a MVP pattern.
One way to overcome this issue is providing any Android dependency using a mocking framework like for example Mockito.
This will be fine if we just need to mock a couple of dependencies with not many interactions between our code and the SDK, but if we have more complex interactions and we need to spend hours mocking classes, this would be a signal that we should run those test in a emulator or device using Instrumentation Test.

To add the tests in the project we haver will need two folders, one for each type of test as you can see in the picture below, the Unit Test lives in the folder named “test” and the UI test are located in the folder “androidTest”. Both have to be at the same level that our main folder of the project. This is important because otherwise Android Studio will not be able to identify these classes as tests.

Screen Shot 2016-04-02 at 20.14.14

 

Anatomy of a Unit Test

So now we are ready to add a Unit Test, to do this just add a new class to the Test folders of your project and now we will have to specify which runner we want to use, the size type of the test, etc. Let’s have a look at the example below and we will go through the different parts.

@RunWith(MockitoJUnitRunner.class)
@SmallTest
public class EmailValidationTest {

    String EMAIL_REGEX = SignupPresenterImpl.REGEX_EMAIL;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void givenValidEmail_RegexCheckReturnsValid() throws Exception {
        String validEmail = "david.guerrero@quoders.com";
        Assert.assertTrue(validEmail.matches(EMAIL_REGEX));
    }

    @Test
    public void givenInvalidEmail_MissingAt_RegexCheckReturnsError() throws Exception {
        String invalidEmail = "david.guerreroquoders.com";
        Assert.assertFalse(invalidEmail.matches(EMAIL_REGEX));
    }

    @Test
    public void givenInvalidEmail_MissingHost_RegexCheckReturnsError() throws Exception {
        String invalidEmail = "david.guerrero@quoders";
        Assert.assertFalse(invalidEmail.matches(EMAIL_REGEX));
    }

    @After
    public void tearDown() throws Exception {
    }
}

@RunWith(MockitoJUnitRunner.class)
We specify the runner we want to use, it might be JUnit runner, the Instrumentation, Automation runner or even a custom runner. It depends on how and where we want to run our test.

@SmallTest
This annotation define the type of test we are runing, where “SmallTest” is usually a Unit Test, a “LargeTest” an end to end UI or Automation test and a “MediumTest” is when we are testing more than one module working together, like an Integration Test. See the table below to compare these different types.
Screen Shot 2016-04-03 at 21.19.34

@Before
The method marked with this annotation will be called every time before a test is launched. It useful to initialise and arrange any data needed for the tests.

@Test
This define a test method. It usually should follow the “Arrange-Act-Assert” pattern:
– Arrange all necessary preconditions and inputs.
– Act on the object or method under test.
– Assert that the expected results have occurred.

@After
This method will be execute after each test and we will use it to release resources, close files, etc.

Running the tests

Finally to run the tests we need to select “Unit Test” on the Build Variant menu. After this we can just right click at the Test package folder and then on “Run Tests..” (or Debug or Run with Coverage).

Screen Shot 2016-04-03 at 21.56.15.png

 

Implementing Integration Tests

As we saw before, these type of test should cover around the rest 30 or 20 percent of our test code base. We will use the Instrumentation and/or Automation frameworks that basically allows us to simulate user interactions on the application that will run in a real device or an emulator.

We are going to use Espresso as our Instrumentation test  framework. With it we can click on buttons, enter texts, do scrolls, etc. See below an example of a Sign Up screen tests.

 

@RunWith(AndroidJUnit4.class)
@LargeTest

public class SingupTest {

    @Rule
    public ActivityTestRule<SignupActivity> mSignupActivityRule = new ActivityTestRule<>(SignupActivity.class);

    @Test
    public void testperformValidCompleteSignup() throws Exception {

        //  Fill up new user fields
        onView(withId(R.id.editTextCreateUserName)).perform(typeText("david_" + System.currentTimeMillis()));
        onView(withId(R.id.editTextCreateEmail)).perform(typeText("david.guerrero@quoders.com_" + + System.currentTimeMillis()));
        onView(withId(R.id.editTextCreatePassword)).perform(typeText("password"));
        onView(withId(R.id.editTextPasswordConfirm)).perform(typeText("password"));

        //  Click on Sign Up button
        onView(withId(R.id.editTextPasswordConfirm)).perform(click());

        //  Check progress dialog is showed
        onView(withText(R.string.signup_progress)).check(matches(isDisplayed()));

        //  Assert Home screen has been launched
        onView(withText(R.string.title_activity_home)).check(matches(isDisplayed()));
    }
}

As we can see in the example, we are introducing all the fields needed to perform a new user registration, then clicking on the Sign Up button and assert that the Home Activity is launched correctly after this.
Notice how we have marked the test with the “LargeTest” annotation and we are running it with the “AndroidJUnit4” runner.
To run this test we now need to change to Build Variant to the “Android Instrumentation Test” option and then we just need to choose where to deploy and run the app and the test, either in a real or emulated device.

Summary

So that was a quite brief introduction to a much more complex subject as the testing strategy in Android. There are much more to talk about testing but that will be probably part of further posts.

You can find these examples on my work in progress open source project Treepolis in Github.

As usual please leave any comments, suggestion or corrections. What’s your testing strategy?

Tagged , ,