API Development

Guarantee Quality by Unit Testing Your Titanium Apps

Guest poster, David Cypers, is a freelance (mobile) solution developer with a strong focus on testability, UX and automation whose broad knowledge about the latest technologies can help you identify the best technology-agnostic solution for your business case. You can follow David on Twitter or LinkedIn. This blog was originally posted on Dzone.

Learn how to run unit testing with the open source testing framework ti-unit, written specifically for testing Titanium apps.

This blog post will explain:

  • Why we decided to write our own testing framework
  • How we unit test our Titanium apps without spinning up a runtime

Why Would You Write Your Own Unit Testing Framework?

Testing is part of A.C.A Mobile’s DNA. In order to deliver quality code, prevent regression and safeguard our developer’s sanity, we write tests.
But tests should execute fast, they shouldn’t be a burden, they shouldn’t slow down development. We want to be able to execute them often, right?

So, we started evaluating some of the tooling around. Despite a lot of community efforts (mockTi, Titanium-Jasmine, Ti-Mocha…), there was no tool which was working out of the box, was easy to use and was fast. Some of these tools were discontinued, some were extremely slow because they ran against the simulator, and so on. Simply said, we didn’t find a match.

It was during a Titanium Netherlands meetup in Amsterdam that we mentioned testing to Axway Appcelerator’s developer advocate. He told us they usually tested the whole app in the container. That evening on our way home, the first ideas about writing such a framework ourselves were born, and the foundation would be built around the following requirements:

  • It should execute fast.
  • It should execute in isolation.
  • It should offer a mock for all functions, constants, and properties in the complete Tinamespace.
  • It should offer the possibility to swap out required dependencies.
  • It should be possible to integrate into our build pipeline.
  • It should be possible to create coverage reports etc on top of it.
  • It would be nice if existing knowledge about (JS) testing could be reused.
  • It would be nice if it would automatically support the newest Titanium API.

And so ti-unit was born.

How to Test Your App With ti-unit

So, how do you write unit tests for your Titanium code?

Installation

First of all, head over to https://github.com/aca-mobile/ti-unit and follow the installation instructions on https://github.com/aca-mobile/ti-unit/wiki.
Also, make sure to copy the files mentioned under https://github.com/aca-mobile/ti-unit#installation.

Perfect, now you are ready to write your first test.

Write Your First Test

Suppose you want to test a controller, which depends on a library, e.g.:

var UserManager = require('user.manager');
function onButtonClick() {
    UserManager.setUserName($.username.getValue());
}
module.exports = {
   test: {
     onButtonClick: onButtonClick
   }
}

First of all:

  • Create a spec folder in the root of your project (folder with  tiapp.xml)
  • Place all your test files inside this folder, the filenames of test files must end with _spec.js.

You don’t want to depend on the real user.manager implementation (we’re testing a unit, right?). Instead, you want to create a mock so you have full control over the user.manager.

So, let’s write our first test:

// create a mock for the Ti namespace based on your own local api.jsca
Ti = require('./jsca.api.parser').parseFromConfig();

// add mocking capabilities for required dependencies
MockRequire = require('tiunit/mockrequire');

var USER_NAME = 'John Doe';

var userManagerMock = {
   setUserName: function() {}
};

// Note: a mock for $ can also be automatically generated, see the wiki for more information
$ = {
  username: {
     getValue: function() {}
  }
};

beforeEach(function () {
   MockRequire.addMock('user.manager', userManagerMock);
   controllerUnderTest = require('../app/controllers/authenticate');
});

afterEach(function() {
   MockRequire.resetMocks();
});

it('should set the user name on the UserManager whenever the button is clicked', function() {
    spyOn(userManagerMock, 'setUserName');
    spyOn($.username, 'getValue').and.returnValue(USER_NAME);
    controllerUnderTest.test.onButtonClick();
    expect(userManagerMock.setUserName).toHaveBeenCalledWith(USER_NAME);
});

And that’s it! Now just execute the jasmine command from within the root folder of your project, and watch your tests succeed.

What Else?

Besides these basic testing functionalities, ti-unit also offers strategies for testing Alloy.CFG, Alloy.Globals, the L macro, the $, callback testing and testing the this context in callback functions.

Conclusion

Unit testing Titanium applications outside the container is easy, thus there is no reason not to do it. Download ti-unit and get started now.

You can find additional samples on the project’s wiki page and in the presentation (all on https://github.com/aca-mobile/ti-unit/wiki).

What’s Next?

In a post to follow, I want to delve deeper into how we solved the topic of (structuring code for) code coverage, library management, delivery pipelines, and reporting.