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.)
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).
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 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:
PhantomJSfor the browser
- Put the paths to your source and test files. I used:
- I didn’t exclude any files
yesto watch files
You’ll end up with a file similar to this:
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
So open up that generated file, and make sure the
files array includes everything you need, and in the right order. First
angular-mocks, then your source and test files. Some dependencies (
jquery) will probably need to go before
angular, and other ones can go after
You may need to
npm install angular-mocks --save-dev if you don’t have
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:
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:
Run the test
Back at the command line, run
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.
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 a Jasmine Cheat Sheet to help you on your way, as well as more Angular best practices and articles on Angular 2, ES6, and more.
Thanks for reading!
Learning React can be a struggle -- so many libraries and tools!
My advice? Ignore all of them :)
For a step-by-step approach, read my book Pure React.