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

How We Guarantee Maximum Quality by Unit Testing Our Appcelerator Titanium Apps

DZone's Guide to

How We Guarantee Maximum Quality by Unit Testing Our Appcelerator Titanium Apps

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

· DevOps Zone ·
Free Resource

Download the blueprint that can take a company of any maturity level all the way up to enterprise-scale continuous delivery using a combination of Automic Release Automation, Automic’s 20+ years of business automation experience, and the proven tools and practices the company is already leveraging.

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 our company'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 Titanium Netherlands' meetup in Amsterdam that we mentioned testing to Appcelerator's developer advocate. He actually 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 Ti namespace.

  • 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 Appcelerator 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.

Download the ‘Practical Blueprint to Continuous Delivery’ to learn how Automic Release Automation can help you begin or continue your company’s digital transformation.

Topics:
appcelerator ,titanium ,unit testing ,devops ,tutorial ,open source ,mobile

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}