Unit Testing A NativeScript Angular 2 Android And iOS Mobile Application

Datetime:2016-08-23 02:35:03          Topic: Test Engineer  AngularJS           Share

Writing tests is a very important part of mobile application development, but not everyone does it.  It could be laziness, it could be because you don’t know how.  I fall into the category that I’m often too lazy to write tests.  I don’t have time to write tests, I just want my application done.  That is probably not a good answer.  Unit testing will lead to overall better applications with less problems down the road.

Not too long ago, Ben Elliot wrote aguest post on The Polyglot Developer regarding unit testing a NativeScript mobile application.  The thing is, that this was directed towards vanilla NativeScript.  While vanilla is a very valid option when it comes to NativeScript, I prefer using Angular 2 which is a bit different.

We’re going to see how to write unit tests for a NativeScript Android and iOS applications that use Angular 2 and TypeScript.

To make this tutorial easy to understand, we’re going to work with a fresh project.  Using a Command Prompt (Windows) or Terminal (Mac and Linux), execute the following:

tnscreateTestProject --ng
cd TestProject
tnsplatformaddios
tnsplatformaddandroid

You’ll notice the --ng tag indicates that we’re creating an Angular 2 and TypeScript application.  Although we’re adding the iOS platform, you won’t be able to build for iOS unless you’re using a Mac with Xcode installed.

The NativeScript CLI makes it very easy to include tests in our project.  Using the command line, execute the following to configure your testing framework:

tnstest init

The above command will ask you to choose which testing framework you’d like to use.  You can use Jasmine , Mocha with Chai, or QUnit .  There is no best framework.  I often use Mocha with Chai, but this time we’re going to use Jasmine.

After the test framework is initialized you’ll be left with a app/tests/example.js file.  The name of this file is not particularly important.  In fact we’ll create a new file in here for every component that we have and name them similarly.

Go ahead and create a file in your project called app/tests/app.component.js which will hold the tests for our project’s  app/app.component.ts file.  Open it and include the following:

var reflect = require("reflect-metadata");
var component = require("../app.component");
 
describe("Tests for app/app.component.ts", function() {
    it("Verify default message", function() {
        var appComponent = new component.AppComponent();
        expect(appComponent.message).toBe("16 taps left");
    });
});

Let’s break down what is happening in the above.

Because our intention is to test an Angular 2 component that contains annotations, we need to include the reflect-metadata dependency.  We also need to define which file we plan to test, being our  app/app.component.ts file.

As of right now we only have one set of tests with a single test.  Out of the box, NativeScript has an app/app.component.ts file that looks like the following:

import {Component} from "@angular/core";
 
@Component({
    selector: "my-app",
    templateUrl: "app.component.html",
})
export class AppComponent {
 
    publiccounter: number = 16;
 
    public getmessage(): string {
        if (this.counter > 0) {
            return this.counter + " taps left";
        } else {
            return "Hoorraaay! \nYou are ready to start building!";
        }
    }
 
    public onTap() {
        this.counter--;
    }
    
}

The counter variable is defaulted to  16 and when trying to access  message this number is prepended to a string of text.  When you first run the application, the string of text will be  16 taps left which matches what we’re testing for in our test case.

If the actual value does not match the expected value, the test will fail.

So how do we actually execute these tests?

From the Terminal or Command Prompt, execute the following:

tnstest android

NativeScript allows you to test on a per platform basis.  Above we are testing on Android, but you could switch to iOS if you wanted to.

Let’s do a few more things in terms of testing this application.  While we won’t add any extra components in this example, there is still stuff to do.

We have an onTap method in our  app/app.component.ts file so it might be a good idea to test it.  However, we want to also reduce some of our unit test code.  If you’re using Jasmine we can run a few things before the test, sort of like a preparation.  The preparation is through the  beforeEach like seen below:

var appComponent;
beforeEach(function() {
    appComponent = new component.AppComponent();
});

We’re doing the above so we don’t have to initialize the component in every test.

The point of the next test is to make sure the onTap method actually decreases the variable.  The complete test code looks like the following:

var reflect = require("reflect-metadata");
var component = require("../app.component");
 
describe("Tests for app/app.component.ts", function() {
    var appComponent;
    beforeEach(function() {
        appComponent = new component.AppComponent();
    });
    it("Verify default message", function() {
        expect(appComponent.message).toBe("16 taps left");
    });
    it("Decrease the tap count", function() {
        appComponent.onTap();
        expect(appComponent.message).toBe("16 taps left");
    })
});

Notice we now have two tests in the same file.  The new test should fail because the actual message should read 15 taps left when it is expecting the count to be  16 .

Conclusion

Unit tests should be included in every application you build.  While people often think they take a lot of time to write or set up, the NativeScript CLI makes them incredibly easy.  Not only can you write unit tests for a vanilla NativeScript application , but you just saw how to write them for an Angular 2 application.

While the official NativeScript documentation doesn’t have information on Angular 2 unit tests, there is still a lot of valuable information on the subject.





About List