Unit Testing Your Ionic Framework App

Unit Testing Your Ionic Framework App

posted in: Uncategorized | 6

Writing Test cases for your mobile application is just as important as it is for every other program. When developing with JavaScript and AngularJS you are prompted with a lot of testing frameworks, it’s sometimes hard to decide which one to take. Therefore this tutorial presents an easy way to start unit testing your Ionic Framework app.

I picked Karma as an environment for running the tests and Jasmine for the actual test cases. These frameworks seem to me as the most reliable for this task, however keep in mind that there are many other options, you need to decide which you prefer for your special case!

Setup an Ionic Tabs demo project

We will start with a simple Ionic Tabs app which offers some controllers we can test out of the box. Moreover we already install the needed npm packages for our testing so go ahead and create all like this:

ionic start ionic-testing tabs
cd ionic-testing
npm install karma karma-jasmine karma-phantomjs-launcher --save-dev

This tutorial uses the 1.0.0-beta.14 Version of Ionic. Additional you need to install the Karma Command Line Interface to run your tests from command line plus finally all our packages we need for the project via npm and bower:

npm install -g karma-cli
npm install 
bower install angular-mocks --save-dev

The angular-mocks will be used for mocking our controllers and finally we create a test folder to have a solid structured project and create a new Karma configuration for our tests:

mkdir tests
cd tests
karma init my.conf.js

For now, leave everything at default when Karma asks for specific settings.

Settings for our Tests and a Gulp Task

We need to make some minor changes to the just created my.conf.js so open the file and change these lines:

// list of files / patterns to load in the browser
files: [
  '../www/lib/angular/angular.js',
  '../www/js/*.js',
  '../www/lib/angular-mocks/angular-mocks.js',
  '**/*tests.js'
],

// Use the PhantomJS browser instead of Chrome
browsers: ['PhantomJS'],

So here we change the files which should be loaded when our tests run, nothing special. Additional we set the browser to PhantomJS as this does not launch an actual browser but runs the tests in the background.

Furthermore I like to have the tests to be run with the same build system I use for other tools, so open the gulpfile.js and add the import and the task:

// Import at the top of the file
var karma = require('karma').server;

/**
* Test task, run test once and exit
*/
gulp.task('test', function(done) {
    karma.start({
        configFile: __dirname + '/tests/my.conf.js',
        singleRun: true
    }, function() {
        done();
    });
});

This will call our test runner Karma with our config file for testing and run the tests once.
If you want to see more useful Gulp Tasks, subscribe to my blog DevDactic for an upcoming post about Gulp Tasks that will save you Time and Money.

Now you are completely ready to set up your first unit tests in your project!

Unit Testing a controller

The first test will test the AccountCtrl which is already included in the Ionic Tabs project. Therefore create a new folder and file at Controllers/controllers.tests.js inside the tests folder and insert this:

describe('Controllers', function(){
    var scope;

    // load the controller's module
    beforeEach(module('starter.controllers'));

    beforeEach(inject(function($rootScope, $controller) {
        scope = $rootScope.$new();
        $controller('AccountCtrl', {$scope: scope});
    }));

    // tests start here
    it('should have enabled friends to be true', function(){
        expect(scope.settings.enableFriends).toEqual(true);
    });
});

This test will just check if the scope.settings.enableFriends is set to true inside the AccountCtrl. The syntax for a test case is actual rather self explaining. The lines before our test are used to set up the environment for the test. beforeEach will be executed before our tests run and get the information of the angular module we want to test, and additional inject the scope to the controller.

The syntax of JavaScript tests is most of the time very clear, so you can read the test case and description and know very fast what this test is about. I think this is a big advantage when regularly using tests in your project.

You can now run gulp test if you have set up the task for this, or with the Karma CLI karma start tests/my.conf.js!

Unit Testing a Service

The second unit test will test the Friends service of the Demo Project. Therefore create a Services/services.tests.js file inside our tests/ folder and add this:

describe('Friends Unit Tests', function(){
    var Friends;
    beforeEach(module('starter.services'));

    beforeEach(inject(function (_Friends_) {
        Friends = _Friends_;
    }));

    it('can get an instance of my factory', inject(function(Friends) {
        expect(Friends).toBeDefined();
    }));

    it('has 5 chats', inject(function(Friends) {
        expect(Friends.all().length).toEqual(5);
    }));

    it('has Max as friend with id 1', inject(function(Friends) {
        var oneFriend = {
            id: 1,
            name: 'Max Lynx',
            notes: 'Odd obsession with everything',
            face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460'
        };

        expect(Friends.get(1).name).toEqual(oneFriend.name);
    }));
});

Here we have again the beforeEach syntax, which injects the Friends Factory and stores it to our local var Friends. Now we can call all the functions of that factory, so we test Friends.all() which should return 5 objects if you use the Ionic Demo project.

Additional we retrieve one specific friend and compare it to our expected friend object. The most important part of this test is just to see how to test a factory/service and it’s functions.

If you are done you can run all the tests again with gulp test if you have set up the task for this, or with the Karma CLI karma start tests/my.conf.js!

Conclusion

The tests I presented in this article are very straight forward and don’t add any real benefit to your project. However, you see how easy it is to integrate Karma and Jasemine into your already existing project. From that point, go ahead and create really useful test cases!

Including tests in your JavaScript project is no problem at all and should always be done. There is no excuse for not having any tests in your project. Even if you are not sure which framework to take, remember, better a not complete matching testing framework than no tests at all!

If you want more tutorials about Ionic, AngularJS and JavaScript make sure to subscribe to my Blog DevDactic and follow me on twitter @schlimmson!

See a video version of this article below.

Application Developer and Process Optimization at arvato Bertelsmann, Germany| Passioned about Apps and Modern Frameworks | Objective-C, Ionic Framework, AngularJS, Java, Python and Javascript | Blogging about Mobile Development and Modern Frameworks on www.devdactic.com

6 Responses

  1. Nice article. Thanks for sharing your experience. I was wondering if it is possible to automate all the test cases. Specially, when you have cordova plugins involved in a app. For example, I have geolocation, image picker, sqlite..etc. plugins used in my controller/services. How do i write test cases for these controllers/services?

    Any help in that direction will be appreciated.

    Thanks.

  2. Very useful post, thanks!

    Just a note, I had some trouble for installing angular-mocks with bower.

    As Ionic doesn’t use the latest angular, you have to specify the angular-mocks version with the angular version used by Ionic (1.3.13 today, see http://stackoverflow.com/questions/22944883/unable-to-find-a-suitable-version-for-angular-with-bower-installation-error-for)

    I had trouble with the new karma version too.

    Just replace:

    var karma = require(‘karma’).server;

    gulp.task(‘test’, function(done) {
    karma.start({
    configFile: __dirname + ‘/tests/my.conf.js’,
    singleRun: true
    }, function() {
    done();
    });
    });

    with:

    var Server = require(‘karma’).Server;

    gulp.task(‘test’, function(done) {
    var config = {
    configFile: __dirname + ‘/tests/my.conf.js’,
    singleRun: true,
    autoWatch: false
    };

    var server = new Server(config, done);
    server.start();
    });

    (see: http://stackoverflow.com/questions/31445614/warning-the-api-interface-has-changed-when-running-karma-on-grunt)

  3. Do you have any examples of using ionic widgets like popover, or modal?

    This shows the basics of jasmine unit tests, but what about when you have ionic widgets on the controller manipulating the scope?

  4. I think this article needs to be updated to reflect the loading of the Ionic files. Also, angular-mocks needs to match up with angular’s version.

    Thanks!!

  5. Thanks for sharing your setup instructions. All I had to change was the included paths to be: files: [
    ‘../www/lib/ionic/js/ionic.bundle.js’,
    ‘../www/js/*.js’,
    ‘../www/js/*/*.js’,
    ‘../www/lib/angular-mocks/angular-mocks.js’,
    ‘**/*/*.js’
    ],

  6. Nice quick tutorial. FYI, the “tabs” template has changed from “Friends” to “Chats”. Might want a note.

Leave a Reply to Sean Cancel reply