Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Mobile Test-Driven Development: Part 3

DZone's Guide to

Mobile Test-Driven Development: Part 3

Today, we culminate this series on best practices for mobile development code quality and testability by looking at writing and running tests from your IDE.

· Mobile Zone
Free Resource

Get gorgeous, multi-touch charts for your iOS application with just a few lines of code.

This post is the third in a series about TDD in mobile development. The previous part of this series can be found here.

This post shows how we can have test driven development for mobile. We will look at options for running our tests from within our IDE and finding the right test runner for our development environment without the need to launch an emulator or deploy to a device every time we want to run the tests.

In the previous post, I showed you how to use NUnitLite to write unit/integration tests on Android and iOS. This post shows how you could write your unit tests with NUnit framework and run them from your IDE.

Problems with NUnitLite

NUnitLite does not have a test runner that can be used outside of the mobile OS. This holds true for both Android and iOS. That’s why every time we need to run the tests, we have to deploy into a real device or a simulator/emulator to run the tests. Now, this could be okay and is necessary for some platform-specific logic. However, in most cases, we do not have to test the code on the exact platform. Take the example that we had in the previous post:

public int GetTotal(int first, int second) {
    return first + second;
}

This code is just plain C# code that could be placed outside of the platform specific code and could be used on multiple platforms, and could then be tested conveniently using NUnit.

Portable Class Library (PCL)

This brings us to using PCL (Portable Class Libraries). The beauty of using PCLs is not only in sharing code across multiple platforms, but it also enables us to test our code using full frameworks like NUnit or Microsoft Test (although I would really stick with NUnit). Bear in mind that PCLs are evolving and every day there are quite a few packages for PCLs coming up.

Some developers might argue that it is troublesome to write your code in PCLs since it adds restrictions and only allows you to use a subset of .NET that is supported on all configured platforms. This could be true, but you can get around it in one of three ways:

1. Only Support the Platforms That You Really Need

I normally use PCL profile 78 or 158. This gives me the two main platforms that I am working on Android and iOS, plus some later versions of Windows phone (8.1), and Silverlight. You do not have to use a profile that tries to support older versions, and you will have fewer limitations by following this approach.

2. Make Use of Nuget Packages

Installing Nuget packages is a great way of doing PCL. Whenever I am trying to do something that is not supported in the .NET subset, I look up the Nuget store, and most of the time I find that somebody has already developed a package that I can just use directly. The other nice thing about Nuget packages is that Nuget supports distributing multiple platforms' libraries. This means that sometimes you get a package that supports Android and iOS. In this case, you would find two separate folders under /lib (inside the Nuget package), one folder for each platform (Android, iOS). In some other cases, Nuget may give you a portable library where you would get folders (under /lib), like portable-win81+net54+ etc. This means that the dlls inside this folder could be used and referenced from within this kind of profiles (Platforms). This is great news because you could just use the code without worrying about changing anything. Examples of such packages are as follows:

a. SQLite.NET-PCL
b. PCLWebUtility
c. Microsoft.Bcl
d. Microsfot.Bcl.Build
e. Microsoft.Bcl.Async
e. Newtonsoft.Json

3. Abstract Your Platform Specific Logic and Use a Platform Specific Implementation

Sometimes your logic has to have a platform specific version. Let’s say you are doing something with animation or cryptography where you need to use the platform specific libraries.
The best way to go about this is to have an abstraction that gets injected into the libraries/classes that depends on these (platform-specific) components. This means that your classes/libraries do not have any dependency on the platform specific code. It is only dependent on abstraction. During run-time, you could inject your platform specific implementation via any IoC container, or even manually. I have a full post on IoC in Cross-platform here. Also, it is worth looking at SQLite.NET-PCL implementation as it follows this approach exactly.

MVVM

MVVM is a great approach for developing software because it ensures that your business logic is not coupled to any presentation layer/component. There is even MVVMCross which allows you to build apps in a cross-platform fashion. However, I do not prefer to go with MVVMCross because it adds much more complexity than I need, and in case I need to develop and change something out of the framework, then I would need to invest a lot in learning and building workarounds. Therefore, what I do is just stick with my ViewModels. This means I take advantage of the MVVM pattern by having my ViewModels holding all my business logic code and injecting these ViewModels into my controllers/presenters. The ViewModels could also have other services, factories, repositories injected into them (using IoC container or manually) and that way our code is all cross-platform and very testable.

    public class CalculatorViewModel: ViewModelBase {
        public int GetTotal(int first, int second) {
            return first + second;
        }
    }

    //iOS Controller
    public class CalculatorController: UIViewController {
        private readonly CalculatorViewModel _viewModel;

        public CalculatorController(CalculatorViewModel viewModel) {
            _viewModel = viewModel;
        }
    }

    //android Controller
    public class CalculatorController: Fragment {
        private readonly CalculatorViewModel _viewModel;

        public CalculatorController(CalculatorViewModel viewModel) {
            _viewModel = viewModel;
        }
    }

Writing Tests

As you can see from above, our logic is now sitting in the ViewModel and it is all testable regardless of the platform. This also makes it easy for us to use any test framework and test runners. This includes NUnit or Microsoft Test. It gets even better; we could even have our test libraries targetting .NET 4.0 or 4.5, which means we could use all the goodness of .NET in writing our tests. This includes using FakeItEasy and RhinoMock.

Running the Tests

Now that we have all this great setup, we can look at running our tests. For using Microsoft Test, this comes out of the box, so there's no need to install anything extra. If you prefer using NUnit like me, then you could install the latest version of NUnit (this includes the adapter and the runner). However, there is an even better way: you could just install NUnit Adapter (with Runner) from the Nuget store. This will make the NUnit adapter and runner part of your solution and you will need to install the framework on all developers machines and your build server (as we will see in the Continuous Integration Server setup later).

To start writing your test, you could create a class library that targets .NET 4.0 or .NET 4.5, and install NUnit Adapter Nuget package, and start writing your tests like below:

Image title

Image title

Running mobile TDD tests in Visual Studio.

Image title

Common mobile TDD tests in Xamarin Studio.

In conclusion, I have demonstrated in the last three posts how to have mobile test-driven development. I hope this motivates you to start looking at improving your code quality and employ some of the tactics we talked about here. If you have any comments and questions, I would love to hear them, so get in touch.

.Net developers: use Highcharts, the industry's leading interactive charting library, without writing a single line of JavaScript.

Topics:
mobile ,tdd ,mobile testing ,mobile app development ,tutorial

Published at DZone with permission of Has Altaiar. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}