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 a guest 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:
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:
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.
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:
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:
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:
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:
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:
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
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.