Thursday, May 26, 2011

Jasmine-Part 1: Unit Testing Javascript

Update: second part is here

As I have already stated in a previous post, I consider unit testing the key to build software that is robust and long-lived :)
Unit testing becomes even more important when you program in a scripting language like Javascript, since you do not have the compiler rescueing you at least from syntactic mistakes.

After playing a little bit with Ruby I could not resist from falling in love with RSpec and its incredible expressivity! So the day I came across Jasmine I had no doubt about what to use to test my JS!

As it says in the introduction the design of Jasmine has been inspired by RSpec but also by other valid alternatives like JSpec.

Jasmine comes in different flavors: stand-alone, Ruby Gem, Node.js module and even Maven plugin! We are going to use the stand-alone version for now. You can download it from http://pivotal.github.com/jasmine/download.html

Downloaded one of the zip, and unpacked in some folder you will find a file called SpecRunner.html. This is the file containing everything you need to setup Jasmine and get started with testing.
Let's have a closer look:



This basically imports Jasmine itself with relative css to make the result's report looking prettier :)

Then we find the files containing the code we want to test:


And finally the tests are imported


Following the head section, in the body you will just find few lines, responsible to actually run the rest

To create a suite of tests you basically need 2 functions:
- describe(): groups tests together providing also setup and teardown hooks
- it(): contains the test itself

Both of them take as first parameter a string, used as a description of what is going to be tested (for describe() ) and what is the expected outcome (for it() ). This is something very familiar to the RSpec's users and it makes it much easier to analyze the results of the tests once they have run.

Other important features are expectations, equivalent to asserts in JUnit.

So let's write a simple unit test for a function validating an email address. According to Test Driven Development let's write the tests first.
Edit a file under the spec folder called demo_spec.js, with:
describe("Email validation", function() {

  it("should validate someone@somewhere.com",function(){
console.log("aaa");
    var result = is_valid("someone@somewhere.com");
    expect(result).toBe(true);
  });

  it("should not validate someone@somewhere",function(){
    var result = is_valid("someone@somewhere");
    expect(result).not.toBe(true);
  });

});
As you can see I used one of the built in expectations called toBe() with the relative not.toBe(), which is the logical not.

Let's now write the is_valid function in demo.js, which will be placed under src:
is_valid = function(email){
  var reg_expr = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
  return reg_expr.test(email);
};
To run the test we also need to modify the SpecRunner.html, so that the head section will look like this:
Jasmine Test Runner
  
  
  
  
  
And finally load SpecRunner in the browser and enjoy the results:




Just for curiosity let's change the second test to:
it("should not validate someone@somewhere",function(){
    var result = is_valid("someone@somewhere");
    expect(result).toBe(true);
  });
It should now fail:







And in fact it does!

13 comments:

  1. Great tutorial. This helped me get up and running with Jasmine. I really appreciate it!

    ReplyDelete
    Replies
    1. After the basics, check out http://believeblog.azurewebsites.net/post/learn-knockoutjs-with-its-father

      You'll see how all the little pieces (Visual Studio, KO, Jasmine, Karma) put together in action.

      Delete
  2. Thanks for the tutorial!

    ReplyDelete
  3. ..but can it be used for js files that reference html elements within the function? I have yet to find any working examples of loading html via fixtures, loading a utilising js file and then being able to test a function that derives values or sets values in the html.

    ReplyDelete
  4. Yes, in this case you need to use spy and fixtures...look at the second part for an example http://a-developer-life.blogspot.com/2011/06/jasmine-part-2-spies-and-mocks.html

    ReplyDelete
  5. Ok thanks - didn't realise that:

    1 - fixtures need to be in spec/javascripts/fixtures if loaded via jasmine-jquery loadFixtures('')
    2 - fixtures load temporarily into SpecRunner.html within a div called 'jasmine-fixtures'.
    3 - I'm probably mistaken here but so far I have to call the loadFixtures() within it() to be able to interact with elements (otherwise I get undefined errors.)

    ReplyDelete
  6. Yes, but you can also call it from beforeEach and save some code.

    ReplyDelete
  7. Thanks Diego for this nice quick start tutorial for using Jasmine unit test framework. This helped me a lot.

    ReplyDelete
  8. Great work here Diego! Is there a way to test a DOM fixture without jQuery? Love jQuery, just wondering if there is a way to test fixtures without it.

    ReplyDelete
    Replies
    1. Hi Jason,
      Of course you can. You could modify the Jasmine-JQuery library itself and remove the dependency from JQuery.

      Diego

      Delete
  9. The download link is dead. It has been moved to https://github.com/pivotal/jasmine/downloads

    ReplyDelete
  10. Tutorial is good to know the basics of Jasmine.

    ReplyDelete
  11. After the basics, check out http://believeblog.azurewebsites.net/post/learn-knockoutjs-with-its-father

    You'll see how all the little pieces (Visual Studio, KO, Jasmine, Karma) put together in action.

    ReplyDelete