Units in your source code are small individual testable parts of your application.Unit testing is a process in which these small units of your code are tested to ensure their proper operation.
AngularJs is designed to make unit testing easier but it also depends on how you organise the code. Unit testing an application where concerns are divided into small independent units is easy rather than a piece of code that does everything.
In this tutorial we will learn to configure our Angular application for unit testing. We will also see an example on how to test custom filters.
This guide requires node installed, as we will be using npm to setup karma andjasmine, if you don’t have node installed then before proceeding further, get node installed.
This guide requires node installed, as we will be using npm to setup karma andjasmine, if you don’t have node installed then before proceeding further, get node installed.
Video
Watch me setting up Angular Application for unit testing with a simple example or scroll below to configuration.
Karma
Karma is a test runner provided by the Angular team, Karma will execute your tests in multiple browsers which shall ensure that our application is compatible in all browsers.
Jasmine
Jasmine is a javascript unit testing framework and will provide us with utilities to test our application. We can use any other javascript testing framework for our testing but we’ll stick to jasmine as it is the most popular.
Configuration
Navigate to your working directory in your terminal or command prompt and follow the below instructions.
- Install AngularJS
- npm install angular --save
- Install Karma
- npm install -g karma --save-dev
- Install Jasmine
- npm install karma-jasmine jasmine-core --save-dev
- Install ngMock
- ngMock allows you to inject and mock angular services to help you test your application.
- npm install angular-mocks --save-dev
- Browsers
- Install browser launcher on which you want karma to run your tests. We need to install atleast one browser. I’ll use PhantomJs.
- npm install karma-phantomjs-launcher --save-dev
- Create two folders in your working directory.
- mkdir app //your script files, controllers,filters etc.
- mkdir tests //here we will keep our tests.
- karma.conf.js
- karma init
- Select Jasmine as your testing framework.
- Select browser, I’ve selected PhantomJS.
- Specify the paths to your js and spec files. Eg. 'app/*.js', 'test/*.js‘.
- After answering a few more questions you should be done.
- Open up your karama.conf.js and add the location of angular.js in to the files array.
- node_modules/angular/angular.js
- Add the location for ngMock just below that.
- node_modules/angular-mocks/angular-mocks.js
That is about it with the configuration, now we can proceed and write our 1st test.
Note: Some commands above may require you to use sudo if you are running on linux.
Your final karma configuration file should look like this.
Note: Some commands above may require you to use sudo if you are running on linux.
Your final karma configuration file should look like this.
karma.conf.js
// Karma configuration
// Generated on Sat Jul 25 2015 19:12:21 GMT+0530 (India Standard Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app/*.js',
'tests/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
})
}
// Generated on Sat Jul 25 2015 19:12:21 GMT+0530 (India Standard Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app/*.js',
'tests/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
})
}
This is the minimum configuration that you’ll need to test your angular application with karma and jasmine.
Testing Pattern
There are a few ways to write your tests to keep it simple and organised, I’ll show you the pattern I follow.
- Describe your object type. eg: Controller, Filters, Factory, etc.
- Inject/load app module
- Describe your specific object name.
- Load mock modules as required
- Initialize your object.
- Describe specific method (for controllers and services)
- Write your tests, expectations.
Unit Testing Example – Filters
Filters are easiest to test, so for this tutorial we will see an example for writing tests for a custom filter.
Lets create a custom filter and write a unit test for it to see if it is working as expected.
Lets create a custom filter and write a unit test for it to see if it is working as expected.
app/app.js – Filter Code
angular.module('MyApp', [])
.filter('reverse',[function(){
return function(string){
return string.split('').reverse().join('');
}
}])
.filter('reverse',[function(){
return function(string){
return string.split('').reverse().join('');
}
}])
Here above if you see we have a custom filter that reverses any string passed to it. Now we need to write unit test for the filter to confirm if it is working as expected.
specs/tests.js – Unit test code
describe('Filters', function(){ //describe your object type
beforeEach(module('MyApp')); //load module
describe('reverse',function(){ //describe your app name
var reverse;
beforeEach(inject(function($filter){ //initialize your filter
reverse = $filter('reverse',{});
}));
it('Should reverse a string', function(){ //write tests
expect(reverse('rahil')).toBe('lihar'); //pass
expect(reverse('don')).toBe('nod'); //pass
//expect(reverse('jam')).toBe('oops'); // this test should fail
});
});
});
beforeEach(module('MyApp')); //load module
describe('reverse',function(){ //describe your app name
var reverse;
beforeEach(inject(function($filter){ //initialize your filter
reverse = $filter('reverse',{});
}));
it('Should reverse a string', function(){ //write tests
expect(reverse('rahil')).toBe('lihar'); //pass
expect(reverse('don')).toBe('nod'); //pass
//expect(reverse('jam')).toBe('oops'); // this test should fail
});
});
});
As you see above we are first describing the object type then loading our angular app. Next we are describing the object by name and initializing our filter then we write our test in the it block along with expectations.
To run the test in your terminal type
karma start
If all the tests passed you should see the below message.
If any of your test failed you will see the bellow message.
If you had troubles seting up karma-jasmine or running the test watch this video tutorial and follow step by step.
Conclusion
Writing unit tests for your application will make you confident about your source code and later it will speed up your development and debugging process.
In this tutorial we learnt how to set up karma and jasmine on our system to Unit test Angular Applications. We also saw an example of unit testing filters. May be in future I’ll write a post on how to unit test controllers, services and directives in AngularJS, let me know about it in the comments or on twitter.
In this tutorial we learnt how to set up karma and jasmine on our system to Unit test Angular Applications. We also saw an example of unit testing filters. May be in future I’ll write a post on how to unit test controllers, services and directives in AngularJS, let me know about it in the comments or on twitter.
No comments:
Post a Comment