Every programer had that awkward moment when something went terribly wrong after a new release. Then you have to run through code, find a bug, fix it, patch it, etc… The worst part is that thing previously was working nice. So what probably happened is that when someone changed a thing, it messed up another thing. It’s not so rare to happen. Speaking of this we come to first reason why you should write unit tests, to prevent regressions. Second reason is that it may influence readability and organisation of your code. For example, you maybe wrote some code which is not so easy to test. Then you have to refactor it a bit, maybe divide it into smaller chunks and then test each of them.
The most common approach to testing is TDD. In TDD, you test “unit of implementation” in this specific order: 1. write falling test; 2. implement functionality and make the test pass; 3. refactor code; BDD is derived from TDD and process is the same, but instead of writing test for functionality, you write a test for specific behaviour.
There is literally a bunch of JS testing frameworks today, but I’ll go through most common one, QUnit, Mocha and Jasmine.
QUnit is the oldest of these three.You need just div in your html and you are ready to go. It has simple API. It has stop()/start() functions to handle asynchronous code testing.
Mocha is another popular testing framework. It doesn’t have assertion library but you can choose one of many. It has a bunch of features and its built on top of Node.js.
Jasmine is, according to GitHub stars, most popular testing framework. It has great asertion library and also (as Mocha) great tools to test asynchronous code. Code style is same as above for Mocha (BDD), but it has it’s own assert library. From here on I’ll give a basic example how to start with Jasmine and how we use it with AngularJS/Grunt/Karma.
First thing you’ll need to do is to download latest Jasmine library from here.
In this purposes I created a simple ‘program’ which takes a string from an input and encrypt it with Caesar cipher.
So first, here is our index.html file:
And here is our Caesar.js file:
We need to understand that our code is not always testable and you have to make an effort to make it that way. Another important thing is that we need to put a focus on testing our business logic. So if you want to test DOM manipulation you better take a look at end-to-end testing. Having these things in mind we can notice that all of our code is within one function and it’s much harder to test it. What we’re going to do is to move text manipulation part into another function so it looks like this:
So after we separated out ‘business’ logic into encrypt function we made it easier for testing. Now we are going to crate another file called CaesarTest.js and put it into test folder.
Now, lets add a check in encrypt function. If value entered is not a string or is undefined return string ‘ERROR’. Add the following code at the beginning of encrypt function
We don’t want to leave this code untested, so lets add another test. We just need to add new it function, describe it and provide test function.
You can also add checks for null or object but I’ll leave that to you.
Ok, so now that we wrote our two tests we need to somehow run it. Stand-alone library comes with SpecRunner.html file and an example how to run tests. So we will just modify file and run it in browser to check the test results.
We should end up with this in our browser
I guess that this is enough for you to understand how to write proper unit tests, so I’ll now show you how we use Jasmine for testing AngularJS.
In next post I’ll try to put closer to you how to test your AngularJS code with Jasmine.