Javascript Specs with Jasmine - A Primer for Rubyists, Part 1

Chris Powers, Jan 25, 2011

Why Test Javascript?

Before talking about Javascript testing frameworks, it's worth answering the more essential question, "Why do we want to test our Javascript anyways?" And it's certainly a valid question. I have heard several people draw back from the very idea of testing Javascript because "it seems like a lot of work just for some lousy regression tests."

And to be frank, I could see their point. There is some significant inertia in building a Javascript test suite, and if their primary goal was simply building test coverage for regression testing, we might decide they get better ROI with manual browser testing. Still, as our Web applications rely more heavily on AJAX and client-side processing, automated Javascript testing is quickly changing from an expensive luxury to a bare-bones necessity.

Why Is Testing Javascript Hard?

The vast majority of developers (both front-end and back-end) have never written Javascript tests. Why not? I think the answer is simple: because it's hard! Javascript testing frameworks and tools have historically been difficult to adopt:

  • Tools that ran tests in the browser (like Selenium) were difficult to configure correctly and usually very slow.
  • Tools that ran outside of a browser were faster and simpler, but were also unable to test DOM behavior.
  • In either case, developers found it very difficult to write tests for their Javascript code because it was often poorly designed, un-modularized and ultimately un-testable.

Test Driven Javascript

The good news is that by using TDD techniques with our Javascript, we can get more benefits that just a nice regression test suite:

  • Enforces Good Design. Javascript code that is written test-first will by necessity be more modular and namespaced, flexible, updatable and reuseable. And, of course, it will be testable!
  • Focus and Process. Developing our Javascript with TDD means that we are writing tests and code that are firmly rooted in the business requirements, helping to keep it simple. By following the TDD "Red, Green, Refactor" pattern, developers can work iteratively and effectively. There is also no ambiguity about when a feature is complete -- when the tests pass, the developer can move on to the next feature.
  • Self Documentation. Using a testing framework that produces legible expectation output gives you a valuable set of documentation as a side effect. The tests themselves can serve as code examples, and developers needing to get up to speed on some Javascript code can use these as learning resources.
  • All this good stuff, and you still get a regression test suite!

Why Use Jasmine?

So if we are sold on the value of test-driving Javascript code, there are still a lot of testing frameworks out there -- why choose Jasmine? It may not be the best choice for everyone, but if you are already a Rubyist familiar with RSpec you'll probably like it:

  • Pairs with RSpec. Jasmine blatantly rips off the syntax of RSpec for your benefit! Not only do they share similar syntax, but they also share similar directory structures inside your Rails app.
  • BDD Approach. Jasmine embraces the BDD style of testing where your specs offer examples of object behavior using a nested scope syntax.
  • For Ruby and Rails. Jasmine ships as a Rubygem and leverages familiar rake tasks and generators to automate common workflows. If you're experimenting with Node.js, it also has its own implementation of Jasmine.
  • Continuous Integration. If you are using a continuous integration server like Hudson, you will be able to plug your Jasmine tests in with minimal configuration.
  • Generative Fixture Support. Jasmine can load in HTML fixtures cached by running RSpec. This means your fixtures are updated every time your RSpec suite is run, and Jasmine will always be using up-to-date markup for DOM related specs.

Getting Started

Getting started with Jasmine is incredibly easy for Rubyists. Start by installing the gem:

$ gem install jasmine

Change into your project directory and run the jasmine generator:

  $ cd ~/path/to/project
  $ script/generate jasmine

Finally, run the rake task to start the Jasmine spec server:

rake jasmine

You should be able to view the spec server at http://localhost:8888, and the example specs should be passing.

To start writing your own specs, first open spec/javascripts/support/jasmine.yml and look at the configuration options. You will probably need to specify your src_files in the order that you want them to be loaded. For example, your jQuery library should be loaded first, followed by jQuery plugins and then your application JS files.

From there, you can start writing Jasmine spec files in spec/javascripts. While you may use any naming convention you like, it is assumed that your spec filenames will end in Spec.js or _spec.js. Some third party tools (namely the TextMate bundle) will give you some extra help if you use RSpec-like naming conventions. For example, if you are testing your JS file public/javascripts/lib/widget.js, the TextMate bundle will guess your related spec file is at spec/javascripts/lib/widget_spec.js.

Keep an eye on the Obtiva RSS feed for my next article where I will go deeper into explaining the Jasmine syntax and compare it with RSpec's syntax.

Jasmine Resources

Rss-icon Rss-icon-over