Click here to Skip to main content
15,879,535 members
Articles / All Topics

Not Testing Your Angular Code? Here's How To Start

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
7 Jan 2016CPOL6 min read 8K   5   1
Not testing your Angular code? Here's how to start

You know you should be testing your Angular code. But you aren’t.

It’s painful, too, seeing article after article espousing the need to test.

Sometimes you don’t even feel like a “real” developer. “Real developers write tests,” they say. “100% coverage is the only way to be sure.”

You’ve Tried to Test

Maybe you tried it once and ran into a roadblock testing directives.

Maybe you never even got that far – Karma and Jasmine and Grunt were just a pain to set up and you said, “Screw it I’ll do it later.”

It Feels Too Late to Start Testing

Perhaps it’s worth giving testing another shot. But where to begin? The tutorials don’t cover how to test your code… and you can hardly just go on Reddit and admit to the world that you’ve never written a test. Those angry test-first people would have a feeding frenzy!

And there’s so much untested code already…

“All or nothing” Is Not the Only Way!

What if you could gradually introduce tests around your code, though? Little by little, the tests would form a scaffold of safety. Right away, you’d be able to refactor the tested parts of your app with complete confidence.

Sounds great, but how exactly do you test all the components in your app? The controllers, the services, and the trickiest of the bunch, directives? They’re all different.

What you need is a set of patterns – “recipes”. If it’s a service, test it this way. If it’s a directive, the test looks slightly different. Promises need their own special magic…

Part 1: Testing Environment and the First Test

To start with, we’ll set up a testing environment, and you’ll write your first test (or your first in a while!), in your own app, and start building that scaffold of safety.

In Part 2, we’ll cover Jasmine’s syntax. And in Part 3, we’ll go over a few Recipes for testing the various parts of your app.

Watch the video for a quick walkthrough to get an Angular test environment up and running with Karma and Jasmine, and write that first test. (Or if video is not your thing, keep reading.)

So you don’t forget to come back for the Testing Recipes post, put in your email and I’ll notify you when it’s ready.

Set Up Karma

Karma is a test runner. Supplied with a configuration file, it will load up your tests along with your app and execute the tests in a browser of your choosing. The browser can be a real one (Chrome, Safari, Firefox, etc.) or a headless one (PhantomJS).

Install Karma

Assuming you already have npm installed, this is easy:

npm install karma karma-jasmine karma-phantomjs-launcher phantomjs jasmine-core --save-dev
npm install -g karma-cli

What’s all this stuff?

  • karma - The Karma test runner.
  • jasmine-core - The Jasmine testing library that supplies the API for our tests.
  • karma-jasmine - A Karma plugin for Jasmine.
  • phantomjs - A headless browser to run the tests.
  • karma-phantomjs-launcher - A Karma plugin to start PhantomJS.
  • karma-cli - A command line tool, installed globally so that you can run karma from anywhere.

Configure Karma

Karma comes with a handy tool for getting started with a configuration. Run karma init and answer the questions, and it will generate a config file for you.

For the sake of this tutorial, answer:

  • jasmine for framework
  • no Require.js
  • PhantomJS for the browser
  • Put the paths to your source and test files. I used:
    • src/**/*.js
    • test/**/*.spec.js
  • I didn’t exclude any files
  • yes to watch files

You’ll end up with a file similar to this:

JavaScript
// Karma configuration
// Generated on Tue Dec 29 2015 21:08:31 GMT-0500 (EST)

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',
      'src/**/*.js',
      'test/**/*.spec.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,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}

Dependencies (Order Matters)

For the most part, this file can be used as-is, except for one section: the files to load. When your app is running in a browser, you’ve got index.html specifying all the dependencies. When it’s running under Karma, you’ve got this config file here.

So, you need to specify paths to your app source and test files (already done), and also any dependencies (UI Bootstrap, moment.js, lodash, etc.). You also need to pull in angular and the not-so-obvious angular-mocks.

So open up that generated file, and make sure the files array includes everything you need, and in the right order. First angular, then angular-mocks, then your source and test files. Some dependencies (jquery) will probably need to go before angular, and other ones can go after angular-mocks.

You may need to npm install angular-mocks --save-dev if you don’t have node_modules/angular-mocks already.

If you get strange errors later (“Can’t find variable: whatever”), come back to this step and make sure you didn’t miss any dependencies.

Karma with Grunt or Gulp

If you use a build tool like Grunt or Gulp, you’ll probably want to integrate Karma with it. For Grunt, use grunt-karma. For Gulp, use gulp-karma. I won’t go into detail about setting these up, but leave a comment below if you want more help.

Write the First Test

With Karma in place, you can write your first test!

Write a Testable Function

Pick a simple service or factory from your app. Add a new method to it called getGreeting that takes a name and returns "Hello (name)". Something like this:

JavaScript
angular.module('demo', [])
.factory('greeter', function() {
  return {
    // ...
    getGreeting: function(name) {
      return "Hello " + name;
    }
  };
});

You might be thinking this is awfully simple, and how will this apply to real code anyway. And you’re right, this is awfully simple.

However, it’s best to test out the pipeline with something we know will work. If Karma fails with some strange error, at least you can be pretty sure it’s not the test code.

Write the Test

Create a new file called getGreeting.spec.js under the test directory (or wherever you configured Karma to load tests from). Type this in:

JavaScript
describe("getGreeting", function() {
  var greeter;
  beforeEach(module('demo'));
  beforeEach(inject(function(_greeter_) {
    greeter = _greeter_;
  }));

  it("says Hello to me", function() {
    expect(greeter.getGreeting("Dave")).toEqual("Hello Dave");
  });
});

Run the Test

Back at the command line, run karma start.

Did you see PhantomJS 1.9.8 (...): Executed 1 of 1 SUCCESS? If so, nice work! You’ve got the base of your scaffold in place!

If something went wrong, it’s likely due to a missing dependency or syntax error. Go back to the dependency setup, and follow the stack trace if you got one.

What’s Next?

In Part 2 of this guide, we look at Jasmine syntax – the anatomy of a test. How do describe, it, and beforeEach work? When and how can they be nested? Those questions are all answered in Part 2!

In Part 3, we’ll look at the different ways to approach testing controllers, services, directives, and promises.

You’ll be able to start getting tests around your app, and start building that scaffold of safety! Sign up for my newsletter and you’ll get Part 3 when it’s out, as well as more Angular best practices and Angular 2 articles.

Thanks for reading!

Not testing your Angular code? Here's how to start was originally published by Dave Ceddia at Angularity on December 31, 2015.

This article was originally posted at https://daveceddia.com/feed.xml

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Dave is a Software Engineer in the Boston area and writes about AngularJS and other JavaScript things over at daveceddia.com

Comments and Discussions

 
QuestionHow to create a dynamic calendar in c#? just like system calendar Pin
Member 1349307429-Oct-17 22:33
Member 1349307429-Oct-17 22:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.