Pragmatic JavaScript Testing with Jasmine

Posted on by in Process, Web

As more and more parts of our applications are written in JavaScript, its important to have them covered with automated tests. Fortunately, there are numerous JavaScript testing tools available. As a BDD fan, the RSpec inspired Jasmine is currently my go-to.

The Basics

For developers coming from RSpec, Jasmine will feel very familiar.

Here’s a simple spec that demonstrates most of the basics:

describe('User', function () {
  beforeEach(function () {
    this.user = new User();

  describe('#age', function () {
    beforeEach(function () {
      this.age = this.user.age;

    it('defaults to 21', function () {

  describe('#save', function () {
    beforeEach(function () {
      this.age = 30;{ age: this.age });

    xit('updates itself', function () {

Use #beforeEach for setup, #describe to group related specs and #it for your examples. The above two examples use the #toEqual matcher. Jasmine comes with basic matchers e.g. #toBe, #toMatch, #toBeNull; check the docs for a complete list. Nested #describe’s are legal but unlike RSpec there’s no #context method.

The last example uses #xit to mark the example as pending. A corresponding #xdescribe also exists to mark a group of specs as pending. These can be useful as a checklist of sorts in a test first workflow.

The abundance of anonymous functions in Jasmine specs can seem a bit strange and verbose but if you’ve done a fair share of JavaScript you’ll quickly get used to it. For those who haven’t just bear with it for now, later I’ll discuss a way to improve the syntax.

Specifying jQuery

With the basics out of the way let’s look at specifying something you’re likely to encounter in every app: jQuery. For jQuery we’ll use the excellent jasmine-jquery library.

jasmine-jquery gives us HTML fixtures and jQuery specific matchers.

Here’s a sample:

describe('thermostat', function () {
  describe('#lossLangage', function () {
    describe('when selecting an inefficient heating temperature', function () {

      beforeEach(function () {


      it('warns how much money you could be saving', function () {

      it('includes the inefficient temperature in the warning', function() {

This spec is for a #change event handler for a <select> element. #loadFixtures is provided by jasmine-jquery and allows you to use external HTML files for test data.

Here’s the fixture file used above:


<select id="temperature">

<div id="warning" style="display:none">

We used two jQuery specific matchers in our examples: #toBeVisible and #toHaveText. These and a lot more are available; be sure to check out the README for the complete list.

If external fixtures files are too heavyweight for your needs jasmine-jquery also provides inline fixtures via #setFixtures.

describe('NewTaskView', function () {
  describe('#render', function () {
    beforeEach(function () {
      setFixtures('<div id="taskForm" />');
      this.newTaskView = new NewTaskView({ model: new Task });


    it('displays a form to enter a new task', function () {

In this spec our fixture was just a simple <div> element so we decided to define it in the spec. With everything defined in one place it makes the spec easier to understand and follow.

Specifying Ajax

Of course no app is complete without some Ajax. For specifying Ajax we’ll use the excellent jasmine-ajax library. jasmine-ajax monkeypatches jQuery to use a fake XMLHttpRequest object. This fake will store all Ajax requests, allowing you to inspect and even respond to them.

Here’s a example:

describe('EditTaskView', function () {
  describe('#update', function () {
    beforeEach(function () {
      this.task = new Task({ id: 1 });
      this.editTaskView = new EditTaskView({ model: this.task });

      $('form', this.editTaskView.el)

    it('updates its task', function () {
      var request = mostRecentAjaxRequest();
      expect(request.url).toEqual('/tasks/' + this.task.get('id'));
      var params = JSON.parse(request.params);

This example uses jasmine-ajax’s #mostRecentAjaxRequest method to get the last Ajax request. We then specify its method, url and parameters.

Specifying the request is great but only half the battle. We also want to specify our response handlers. Let’s extend the above example with a spec for a failing update:

describe('EditTaskView', function () {
  describe('#update', function () {
    ... // existing successful update spec

    describe('given an invalid task', function () {
      beforeEach(function () {
        this.task = new Task({ id: 1 });
        this.editTaskView = new EditTaskView({ model: this.task });

        $('form', this.editTaskView.el)

      it('displays any validation errors', function () {
        var body = {
          description: ["can't be blank"]
        var response = {
          status: 422,
          responseText: JSON.stringify(body)
        var request = mostRecentAjaxRequest();
        expect($('#errors', this.editTaskView.el)).toHaveText("Description can't be blank");

Our failure specification uses the jasmine-ajax request object’s #response method to simulate a non-success response from the server.

Running Your Specs Headlessly

The Jasmine gem comes with two Rake tasks that you can use to run your specs. rake jasmine will start a Ruby web server to allow you to run your specs from a browser. For those of us who live on the command line and can in no way fathom running tests from a browser there is rake jasmine:ci. Unfortunately this will use Selenium to run your tests in Firefox.

Instead I like to use the jasmine-headless-webkit gem to run specs headlessly with WebKit. jasmine-headless-webkit includes a command line app that can be used to run every spec at once or a single spec at a time.

# run all specs (will try to locate your jasmine.yml config to determine what specs to run)
$ jasmine-headless-webkit

# run an individual spec
$ jasmine-headless-webkit spec/javascripts/models/task_spec.js

jasmine-headless-webkit also supports specs written in CoffeeScript.

Cleaner Specs with CoffeeScript

CoffeeScript is a fantastic language that compiles into JavaScript. Syntactically it really cleans up JavaScript and feels a like a mixture of Ruby and Python.

Here’s a previous spec converted to CoffeeScript:

describe 'NewTaskView', ->
  describe '#render', ->
    beforeEach ->
      setFixtures '<div id="taskForm" />'
      @newTaskView = new NewTaskView model: new Task


    it 'displays a form to enter a task', ->

Basically CoffeeScript is JavaScript with no semi-colons, curly braces, 1/2 the parentheses, a simpler function syntax, Ruby style instance variables, Python style formatting and a whole lot of functional goodness. If you haven’t checked it out yet I suggest you do. Although once you do, you won’t be going back to plain old JavaScript anytime soon.

Start Testing Today

Jasmine is a mature, proven JavaScript testing tool. Coupled with a great community turning out testing tools everyday, there is no longer any excuse to be writing untested JavaScript. So quit putting it off and give it a try today.


  Comments: 26

  1. Michael Wynholds

    It seems like JS testing has been around forever (ie: several years), but I always felt the tools out there sucked. I haven’t used Jasmine yet. Do you have a similar feeling about previous tools? And is Jasmine the silver bullet, or is it just a little better than previous tools? What I’m basically asking is this – will Jasmine make unit testing JS easy enough that testing becomes the norm (like it is in Ruby)?

    Two other things:
    1. I’d love to see an example of some output from the jasmine-headless-webkit test runner.
    2. I’d love to see another post focused on CoffeeScript.

    • Jared Carroll


      I started out with JsUnit, then JSpec, and jQuery’s QUnit. JsUnit and JSpec are no longer maintained and QUnit is a classic xUnit style of testing. After using RSpec in Ruby I prefer the BDD style of specifications rather than tests; so naturally I decided to use Jasmine. I’d say Jasmine is better than previous JS testing tools because its got a good community, is actively maintained and addresses common JS use cases. As for developers writing JS tests, the community just needs to get behind testing like the Ruby community did; with the appearance of new testing tools I think it will become more commonplace.

      Check out the jasmine-headless-webkit page for an example of its output. There’s nothing surprising there, its just like traditional testing tools.

      I’ll see what I can do about CoffeeScript 😉

  2. I have been using backbone.js and I have separated my Jasmine specs according to the MVC pattern. My directory structure for my specs look like:

    – controllers
    – models
    – views

    With a spec for each layer, I have found that my client-side TDD flow has improved as I build out my features from the top down.

    Sidenote: one big advantage that I noticed when using jasmine-headless-webkit was the speed. All of my specs finish running under a second using jasmine-headless-webkit.

  3. Giles Bowkett

    I like to use the Node.js fork of Jasmine, jasmine-node, to run specs on the command line. The upside is it’s crazy fast. The downside is that DOM and jQuery integration were, last I checked, kind of a PITA. However, the more you factor your code in an MVCish way, separating logic from view specifics, the less that matters, and it’s really nice to have even just a model-centric section of your code base where JS specs run headless and lightning-fast.

  4. Dmytrii Nagirniak

    I just want to add couple of things:

    1. You can automatically run specs as files change using guard and guard-headless-webkit.
    2. You can automatically compile Rails 3.1 assets using guard-rails-assets (

    With these 2 gems it the BDD gets much closer to you.


  5. Seems like jasmine-ajax is incompatible with jasmine-jquery#loadFixtures function as it uses an ajax call to retrieve the fixtures. Have you already fallen into this problem?

    • August Jaenicke

      The lastest version of jasmine-query (1.3.0) adds a preloadFixtures method to get around the conflict with jasmine-ajax. Using preloadFixtures worked for me – but it seems you need to call it outside of the it/describe block where you call loadFixtures. Then all is good.

      See this post by velesin for more information:

  6. Jared Carroll


    I’m sorry I haven’t run into that issue. I would say move towards using jasmine-jquery#setFixtures and define all your test data in your tests. That’s currently my strategy.

  7. Charles Serra

    Nice article, Jasmine BDD seem’s really awesome.. It is possible to save a set of result directly on a database? It would be very usefull.. Thanks!

    • jasmine-headless-webkit doesn’t save the entire set of results, but I can definitely see the value in doing so for CI servers. RIght now, it can write out a basic report file, but that’s primarily for Guard notifications. Open a new issue on the GitHub project ( with the kind of format you’re looking for and we can get it added to a future release. 🙂

  8. Jared Carroll


    I’m not aware of any easy way to save the results from running a full test suite with jasmine-headless-webkit to a database. You would probably have to roll your own script.

    • Charles Serra

      Thanks you for your answer! I browse the jasmine code source for a while, and all results a contained in a variable. Currently, I don’t know if I can get it from an external script.. but I think it should be possible… Let you know if I find something 🙂

  9. hi,

    The “loadFixture” helper method is great but, this requires me to have that HTML snippet both in my pages and also in the snippet file to be called by “loadFixture”. This is not optimal since, these two things can go outta sync and cause issues. Any help/suggestions to get around this issue?

    Thank You,

    • Vish,

      I agree in that keeping the two in sync is a pain. Here’s an interesting solution that uses regular RSpec tests to generate html fixtures for JS tests: . Another approach would be to use client-side rendering for all your markup (think backbonejs).

      • great. i will check out that RSpec stuff. Also, even if i use all client-side templates, i would still have to have them in 2 places right? One in my page itself and second in a separate file so that loadFixture can load it in?

        Thank You,

        • August Jaenicke

          I’m currently using knockout + jquery.tmpl with testing in jasmine. I use a modified version of the rspec helper from that pivotal post to process my haml files (with the embedded templates) into a tmp directory in my project. My only significant mods to the pivotal code was to update it to work with the latest rails/rspec. Then I use jasmine-jquery’s new preloadFixtures to load from that directory. (I have to use preload instead of load due to the conflict between mock-ajax and jasming-jquery). Works great. The only catch is that I have to remember to run the rspec that saves the processed haml before running the jasmine tests when I modify the original haml. Other than that, it’s been a great way to test.

        • @vish,

          By using client-side rendering I was thinking of generating the markup via a framework like backbonejs and then programmatically accessing it in a Jasmine test via a backbonejs View object. This would require more JS but it would minimize and possibly eliminate the need for html fixtures. Although this is most likely overkill for most apps.

          Here’s a good intro to testing backbonejs: . A little old but most of it still applies.

  10. Hey,

    I’m trying to use the jasmine by the jessie (node.js headless) and then I would like to test:

    it(“should change the pc”,function(){

    function cpuStep(){return 5;}

    And then run it through terminal: jessie /spec -f nested

    But for sure the cpuStep function is not defined, how can I include / load or anything else to append this dependencies of my spec?

    • @leandro – I haven’t yet tried out jessie but it seems to be based on jasmine-node which like normal jasmine will look for non-test code in the directories specified in your jasmine.yml file.

  11. After the basics, check out

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

  12. This is a comment to the admin. I discovered your page via Bing but it was hard to find as you were not on the first page of search results. I know you could have more traffic to your site. I have found a company which offers to dramatically improve your website rankings and traffic to your site: I managed to get close to 1000 visitors/day using their service, you could also get many more targeted traffic from search engines than you have now. Their service brought significantly more traffic to my site. I hope this helps!

  13. Connect with local girls. Watch them live, chat with them, and then meet them for some adult fun! Meet Local Girls Today

  14. Balaji Travels by Rasabihari Ramkrishna Sikdar is a SCAM!

    Balaji Travels by Rasabihari Das is a SCAM. DO NOT EVER USE THIS SERVICES! IT IS PURE CHEATING! His phone number is +91-9564242119 and his email is . Once again, DO NOT EVER buy from Rasabihari Das or from Balaji Travels. They are all cheaters and scammers!!!!!

  15. tomorrow !party raffle
    Huge online casino wins – online casino 15 euro bet big win –
    garden of riches huge win

    After a short visitto her water box,sheput onmy lead andwe wentoff forher usual casino session.
    I don’t normally make use of IGT slots while i like to give full attention to
    Williams, NETENT and Micrograming inside my Twitch Casino Stream.

    Unibet supplies a wide range of online casino games with fresh bonuses for players.

    Enjoy William Hill’s UK Live Casino with Exclusive Live dealer Games.

    Compare 5 hotels near Casino Arizona in Scottsdale using real guest reviews.

    Download Slots Free – Big Win Casino™ Apk 1. Play Online Blackjack, Roulette, Baccarat and Texas Hold em on Bwin with the Live Casino Dealers.

    Look no further for the most effective free slots and casino
    Online Live Casino at 888casino could be the next degree
    of online casino games.

Your feedback