Using Jasmine To Test JavaScript

posted on 10/24/12 at 04:24:06 pm by Joel Ross

I'm not good at writing JavaScript. I know that. I'm trying to get better, but JavaScript development still feels like the Wild, Wild West of software development to me. To help fix that problem, I've started to investigate ways to get better. First, I looked at Backbone, and that helped quite a bit because it really leads you to organize your code. But the more I thought about it, the more I realized that what I wanted was a way to verify that the code I was writing actually worked. So I did a little research on JavaScript unit testing. I found a few different options. The one I liked the most was Jasmine, because it follows closely with the style of tests that I write at TrackAbout.

To get started, I wanted to do something simple, so I did a couple of Katas. Doing a kata was nice because the code I was writing didn't have any external dependencies (like the DOM), and it allowed me to focus solely on learning Jasmine.

Getting started with Jasmine isn't all that difficult. First, you create a simple HTML file that will act as your test runner. You need to include references to a few Jasmine files, your class under test, and your tests. Then you fire up the Jasmine environment and run the tests.

   1: <html>
   2:   <head>
   3:     <title>FizzBuzz Specs</title>
   4:     <link rel="stylesheet" type="text/css" href="jasmine.css">
   5:     <script type="text/javascript" src="jasmine.js"></script>
   6:     <script type="text/javascript" src="jasmine-html.js"></script>
   7:     <script type="text/javascript" src="FizzBuzz.js"></script>
   8:     <script type="text/javascript" src="FizzBuzz.specs.js"></script>
   9:   </head>
  10:   <body>
  11:     <script type="text/javascript">
  12:       jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
  13:       jasmine.getEnv().execute();
  14:     </script>
  15:   </body>
  16: </html>

For simplicity, the file looks like I have all of the files in one directory. The actual repository is organized a little bit better than that.

The Kata I chose was FizzBuzz, since it's a pretty simple one and I wouldn't get bogged down in the code. My first spec looked like this:

   1: describe('FizzBuzz specs', function() {
   2:     var fizzBuzz;
   3:  
   4:     beforeEach(function() {
   5:         fizzBuzz = new FizzBuzz();
   6:     })
   7:  
   8:     describe('when passing in a simple number', function() {
   9:         it('It should return that number', function() {
  10:             var result = fizzBuzz.getOutput(1);
  11:             expect(result).toEqual('1');
  12:         });
  13:     });
  14: });

You start each test with a call to describe, giving a description and a function for what this will test. You can have a setup method (beforeEach()) that will handle any set up, and you can nest describe calls to handle more set up. The heart of the test is the It() method, because this is where you verify your results. In the method above, I'm validating that if you pass in 1, you get the string representation of it back.

The documentation for Jasmine is very good, and goes over all the different ways you can set up expectations, so I won't touch on that here - they say it much better than I could.

Back to our example. Without any implementation, I ran the specs to see what I got.

FizzBuzzFailingTest

One test and two failures. That sounds like success to me! But I thought a passing test would be a bit better, so I added a simple class that lets the test pass.

   1: function FizzBuzz() { }
   2:  
   3: FizzBuzz.prototype.getOutput = function(input) {
   4:     return intput.toString();
   5: };

Rerunning the test now reflects that.

FizzBuzzPassingTest

I then went ahead and finished out the tests and the implementation (available in my Jasmine repo on GitHub). When done, I ended up with six tests that all passed.

FizzBuzzAllTestsPassed

Like I said, it's a fairly simple exercise, but it definitely gave me a feel for what Jasmine could do. Next up was to try it against a real world example, but I'll save that for another post.

Discuss this post!

Categories: Development