Jasmine for JavaScript Testing: It's Screw.Unit++

I'm pretty excited about Pivotal's JavaScript testing framework, Jasmine. The same folks who brought us Screw.Unit have upped their game. You still get the RSpec-style JavaScript DSL that you know and love, but Jasmine's a bit leaner and meaner, has a more robust architecture under the hood, and is sporting several exciting new features. I'm making plans now to move the Relevance fork of Blue Ridge over to use Jasmine instead of Screw.Unit.

New Infrastructure: No DOM or jQuery

Screw.Unit's biggest weakness is that it uses jQuery to store all its data in the DOM. The tests its going to run, their before/after behaviors, and whether they passed or failed -- it's all stored as attributes on DOM objects. It was a clever hack and works well enough for in-browser tests, but it causes trouble for headless testing.

Here's why: env.js is our DOM simulator. It pretends to be a browser, modeling HTML as JavaScript DOM objects. It strives to be an idealized DOM, separate from any particular browser's implementation. This is a pretty ambitious goal, and env.js does a pretty good job of it.

However, jQuery exercises the hell out of the DOM, and it really pushes env.js' buttons. It has to, since jQuery's biggest job is to adapt itself to whatever browser is running it. It pokes and prods env.js to understand its capabilities, and every new version of jQuery adds new tests. So, just about every time a new version of jQuery is released, it exposes areas of the DOM that env.js hasn't yet implemented, sometimes causing it to crash.

This situation isn't ideal, but it's workable if only your tests that exercised a particular part of the DOM failed due to the jQuery/env.js interaction. However, we often see these problems right away, as jQuery tries to determine capabilities early, sometimes stopping Screw.Unit immediately. Zero tests run. That is unacceptable.

Jasmine (like JSpec) doesn't need the DOM when it's not testing the DOM. It doesn't need jQuery when it's not testing jQuery. Jasmine was designed from the ground-up to be as stand-alone as possible. The folks at Pivotal have listed that as one of their most important design goals.

Easy Install & In-Browser Testing: The Jasmine-ruby Gem

The Jasmine-ruby gem is a Ruby program that generates Jasmine test scaffolding and that can run a small Ruby webserver to serve up your HTML fixtures. My favorite part of this is how environment-independent it is. No matter whether you're writing a Ruby on Rails app, a PHP website, a jQuery plugin, or even a Clojure webapp, it's the same command to generate and run your specs in-browser.

Other New Features

  • Leaner DSL:

    • Only superficial differences.
    • No longer wraps the whole test suite in a "Screw.Unit()" function.
    • Replaced Screw.Unit's matchers with a more JavaScript-y, camelCase syntax.
  • Asynchronous Testing Support

    • Learning from QUnit and JsUnit, Jasmine added testing tools for timers.
    • Very important for testing visual jQuery plugins, animations, etc.
  • Spies

    • Built-in mocking & stubbing.
    • Built-in "did-it-call-my-method?" checks.
  • Officially Maintained

    • Screw.Unit is basically abandonware.
    • Jasmine, however, is seeing active support from Pivotal.

Conclusion

So, a familiar DSL, less worries about the DOM and jQuery compatibility, and nifty new features -- I'm pretty excited to be using Jasmine. So long Screw.Unit, and thanks for all the fish.