Angular 1, AngularJS

Unit testing using Karma

One of the most brilliant feature of Angular is testing aspect, which is normally carried out using Karma. Karma has such a brilliant functionality for testing Angular code, that it just makes sense to use this framework.

Here we are going to see how to write tests for addition of two numbers using Karma (Angular 1).

Introduction to Karma

A simple tool that allows you to execute JavaScript code in multiple real browsers. The first step for using Karma is to install Karma. Karma is installed via npm (which is a package manager used for easy installation of modules on a local machine).

1. Installing Karma

Navigate to your working directory in your terminal or command prompt and follow the below instructions.

mkdir angular-karma
cd angular-karma
echo {} >> package.json

Now install karma using npm package manager.

 npm install karma --save-dev

Once done with above step we can see following section in our package.json

 {
  "devDependencies": {
    "karma": "^1.4.1" // (this version may be different)
  }
}

Now install the karma-cli (for Windows user to use Command Prompt) since it makes the command karma globally available:

npm install -g karma-cli

The next step is to install karma plug-ins to enable us to use the Jasmine test framework and Google Chrome as the target browser:

 npm install karma-jasmine karma-chrome-launcher --save-dev

Once done with this step we can see following in package.json :

{
  "devDependencies": {
    "jasmine-core": "^2.5.2",
    "karma": "^1.4.11",
    "karma-chrome-launcher": "^2.0.0",
    "karma-jasmine": "^1.1.0"
  }
}

2. Project Configuration

Create two folders in your working directory(in our case root directory: angular-karma)

mkdir app    //your script files, controllers,filters etc.
mkdir tests   //here we will keep our tests.

First create configuration file karma.conf.js

To run the tests first we need to create configuration file for karma settings.Enter the following command to create this file.

karma init karma.conf.js

It will ask for some questions. Answer these question as follows :

  • Which testing framework do you want to use?
        Hit enter to select default value as Jasmin Framework
  • Do you want to use Require.js ?
    Hit enter to select default value i.e. no.
  • Do you want to capture any browsers automatically ?
    Hit enter to select default value i.e. Chrome.
  • What is the location of your source and test files ?
    Enter this value ‘app/*.js’, ‘test/*.js’.

    (we can enter these values manually later in files: [] section of karma.conf.js file)
  • Should any of the files included by the previous patterns be excluded ?
    Hit enter to accept the default value.
  • Do you want Karma to watch all the files and run the tests on change ?
    Hit return to accept the default value. i.e. yes

The config file called karma.conf.js will be created in the root folder.

Now Update the package.json file as follows :

{
    "scripts": {
    "test": "karma start karma.conf.js"
  },
  "devDependencies": {
    "jasmine-core": "^2.5.2",
    "karma": "^1.4.11",
    "karma-chrome-launcher": "^2.0.0",
    "karma-jasmine": "^1.1.0"
  }
}

This change means that we can enter npm test rather than the specific karma configuration detail.

Now create lib folder in project root directory and add angular.min.js and angular-mock.js files into that folder. (You can download these two files from net with latest version.
https://code.angularjs.org/1.4.0-rc.2/angular.min.js
https://code.angularjs.org/1.4.0-rc.2/angular-mocks.js

Open up your karma.conf.js and add the location of these two files into the files array.
Replace this section

// list of files / patterns to load in the browser
files: [
 'tests/*.test.js'
],

With this section

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

With this we are done with karma settings.

3. Controller and Test logic 

Now it’s time to write controller logic and test for that controller.

Create file “numberAddition.controller.js” into app folder.
This controller contains the logic for addition of two numbers. Paste following code into this file.

// numberAddition controller
angular.module('numberAdditionApp', []).controller('numberAdditionController', function numberAdditionController($scope) {
  $scope.total = 0;
  $scope.sum = function() {
    $scope.total = $scope.num1 + $scope.num2;
  };
});

Create file “numberAddition.controller.test.js” into tests folder. This file contains the test cases for numberAdditionController.

Paste the following code into this file.

//test for numberAddition controller
describe('numberAddition', function () {
  beforeEach(module('numberAdditionApp'));
  var $controller;
  beforeEach(inject(function(_$controller_){
    $controller = _$controller_;
  }));
  describe('sum', function () {
		it('2 + 3 should equal 5', function () {
		var $scope = {};
		var controller =
                 $controller('numberAdditionController', { $scope: $scope });
			$scope.num1 = 2;
			$scope.num2 = 3;
			$scope.sum();
			expect($scope.total).toBe(5);
		});
	});
});

The above code has the following aspects

  1. The describe function represents a spec (logical grouping of tests). The it function indicates a test within the logical grouping.
  2. Here we introduced expect and toBe functions from the Jasmine framework. Expect (called an Expectation) takes the expression we wish to test and wraps it so that we can call functions to assert the result of the expression evaluation. The functions we can call, are called Matchers (the function toBe).

4. Reference Jasmine Code Guidelines

  • Suite’s :
  • Specs & Expectation :

Suite’s 

Suite’s are like class in object oriented languages like Java, C# which can contain one or more test case methods.

describe () which takes two arguments. The first argument is the name of the suite and the second argument is the JavaScript function containing initialization functions and specs.

describe('numberAddition', function () {
...
}

Specs & Expectation 

It is a test case which can be defined by calling global Jasmine function called it () which again takes two arguments like suite. The first argument is the name of the spec and the second argument is the JavaScript function containing one or more expectations.

Expectation is built with Jasmine function called expect (). Expect function takes a single argument which represents the actual value and compares it to the expected value with the help of a matcher function.

5.Running Sample Test

We are done with everything . Now run the following command .Go to project root directory using command prompt.

cd angular-karma
npm test

If all went to plan, the output console should show something like this:

karma-code.png

6.Running Negative Test Case

Now as we have written code for testing , we should also test for negative test cases. So let’s just for the curiosity we will check for one negative test case.

For this do the following changes in our numberAddition.controller.test.js.

describe('sum', function () {
		it('2 + 3 should equal 5', function () {
			var $scope = {};
			var controller = $controller('numberAdditionController', { $scope: $scope });
			$scope.num1 = 1;
			$scope.num2 = 3;
			$scope.sum();
			expect($scope.total).toBe(5);
		});	
});

One done with this change now observe the output. You will get output something like this : karmaTestCase.png

We have written test to get expected output as 5
expect($scope.total).toBe(5);
 But we are getting it as 4. Therefore it is showing our test is failed.

Download sample code from zCon Solutions Github Repo


Written by Dipali Shinde , Sr. Software Engg. at zCon Solutions 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s