AngularJS–Part 7, Getting ready to test

Introduction

This is a series of posts about AngularJS and our experiences with it while migrating the client of a complex enterprise application from Silverlight to HTML5/CSS/JavaScript using AngularJS as a framework. Since the migration is a very ambitious undertaken I want to try to chop the overall problem space in much smaller pieces that can be swallowed and digested much more easily by any member of my team. So far I have published the following posts in this series

Test driven development (TDD) is very important when developing a web application with a rich client since JavaScript is a dynamic language and thus there is no compiler making sure that our code behaves like expected. Tests are our only safety net. Writing tests in JavaScript and running them in a browser is not trivial. Lately the situation has improved quite a bit. Still, to get up and running for the first time is a non trivial task.

Setting up the system

Please note that I am using a laptop with Windows 8.1 as the operating system. But the following setup should also work without any modifications on Windows 7 & 8.

To run unit tests we are going to use Karma (previously named Testacular). Karma is a test runner created by the AngularJS team at Google. Similar to AngularJS itself it is open source. To write the tests we will use Jasmine which is a behavior driven JavaScript test framework or DSL.

A prerequisite for Karma is node.js. Thus please install node.js on your computer

Open a console in admin mode. Preferably use an advanced console like Console2. Use the Node package manager (NPM) to install Karma. We want to install it globally thus use this command

image

Now we need to configure Karma for use in our project

image

This command generates a configuration file (it is a JavaScript file exporting a settings object) that defines

  • which test framework to use (Jasmine in our case),
  • which files to monitor and use (this includes at least)
    • angular.js
    • angular-mocks.js (contains the definition for module and inject)
    • our own code to test
    • the files containing the tests or specifications
  • what browsers to use to run the test against (we’ll stick with Chrome)
  • The port on which the server is listening
  • whether to run the test automatically or manually when any of the monitored files changes

This is my configuration file after manually tweaking it

image

Once we have configured Karma correctly we can run it (remember Karma is a test runner) by using the following command

image

Karma will now monitor all the files we have declared in the config file and run the tests if any of those files changes.

When starting up Karma starts up an instance of the browser(s) we defined in the configuration file. The browser listens at the port also defined in the configuration file.

image

We do not need to observe the browser instance any further and can minimize (not close!) it, since it won’t show any test results. All test results will be shown in the console window where we started Karma. Since we do not yet have any files containing tests Karma will report an error that no matching files were found.

image

But we also know that we have correctly configured our system and we are now ready to write our first tests.

Writing our first test

First we copy the two files angular.js and angular-mocks.js into our application directory. Then we create a new subfolder js and add a file sample.js to this new folder. Using e.g. Sublime we define a simple controller called SampleCtrl which does nothing else than initialize a property hello on the $scope of the controller.

image

This is the controller we want to write a test against. Create a new directory test and add a file sampleSpec.js to this directory. This file will contain our tests that we write using Jasmine. Please refer to the Jasmine documentation for details about the syntax.

We want to write tests against the SampleCtrl controller, thus we write

image

This roughly corresponds to a test class in C#. We provide a description of the scenario as the first parameter of the describe function and a function containing all our test arrangements, the test act and the test assertions (AAA = arrange, act, assert) as second parameter.

To arrange or prepare our tests we can call the method beforeEach. As first we need to make sure our application module is instantiated. Thus we write

image

Where we use the module function provided by angular-mocks.js.

Next we need to configure our controller. In looking back at how the controller is coded we realize that it is a function that gets the $scope injected. To be able to test we need to replace the $scope with our own scope object which we can then later you to execute assertions against. Thus we write

image

Here we use the inject function defined in angular-mocks.js to provide us the $controller and the $rootScope service via injection. We then use the $rootScope as our scope and use the $controller service to get an instance of the SampleCtrl controller. The second parameter of the $controller service call is the parameters that get injected into the controller. In this case it is only one parameter – the $scope – which we provide here.

Having configured everything we are now ready to write our first assertion. For this we can use the it function provided by Jasmine.

image

I have on purpose made a little mistake and I’m expecting “Hello John” without point instead of “Hello John.” with point. I want us to see how a broken test looks like in the output of Karma. The complete code of the specification should look like this

image

When we save this file and switch to Karma we should see the following output

image

The output clearly says that one test was executed and it failed since the expected value did not correspond to the actual value. Let’s correct this in the specification and save the file again. Karma will now output this

image

and we are happy and can go have a beer Smile

Yes, I’m aware, this was not TDD what I demonstrated so far since I first wrote the code and then the test. But this post was mainly about getting our system setup correctly and ready to start TDD.

Summary

In this post I have show how to setup our system to be able to write unit tests for an AngularJS application. We are using Jasmine as the test framework and Karma as the test runner. A crucial step in the whole setup is to author the correct configuration file for Karma.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 12 years as an independent consultant, trainer, and mentor mainly on the .NET platform. He is currently working as chief software architect in a mid-size US company based in Austin TX providing software and services to the pharmaceutical industry as well as to many well-known hospitals and universities throughout the US and in many other countries around the world. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in AngularJS, introduction, Setup, TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.