Blog Posts tagged with: blue-ridge

Mar 02 2010

Comments

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.

May 12 2009

Comments

Blue Ridge 1.0: JavaScript Unit Testing for Rails. Scandalous!

You wouldn’t consider developing a Rails application without having a solid test suite for your Ruby code, but you’ve somehow convinced yourself to cross your fingers and look the other way when it comes to JavaScript. It doesn’t have to be that way.

Meet Blue Ridge, a Rails plugin that brings the goodness of test-driven and behavior-driven development to your unobtrusive JavaScript code in a Rails-friendly manner.

Blue Ridge

Historically, when selecting a JavaScript testing solution, you were forced to choose whether you wanted a framework that could run your tests in the browser or one that could only run your tests in a headless fashion. By providing a friendly convention-over-configuration wrapper around a collection of open source tools, Blue Ridge gives us the best of both worlds: fast, automation-friendly, and headless testing plus the ability to run your tests in whichever browser is acting up on any given day.

Last summer, Blue Ridge was just a twinkle in our eye. Last week, Blue Ridge made its public debut at RailsConf. Today, we’re pleased to announce version 1.0.

Getting Started

First, install Blue Ridge into your Rails app:

  ./script/plugin install git://github.com/relevance/blue-ridge.git
  ./script/generate blue_ridge

Blue Ridge creates a small example spec to get you started. Run your JavaScript specs to make sure that all is well so far:

  rake test:javascripts

(Hint: You can also use the `spec:javascripts` or `examples:javascripts` aliases. Blue Ridge is compatible with your testing framework of choice, be it test/unit, RSpec, Micronaut, Shoulda, test-spec, etc.).

Next, try running an individual spec. When you installed Blue Ridge, it created a spec file named “application_spec.js”. You can run it like so:

  rake test:javascripts TEST=application

Of course, you really want to generate a spec that’s specific to your app. Let’s say you want to write some tests for a JavaScript file called “public/javascripts/graphics.js”. Run:

  ./script/generate javascript_spec graphics
  rake test:javascripts TEST=graphics

Cool. We can run our JavaScript specs from the command line, and they’re fast! But you just got a bug report regarding JavaScript errors in IE6 (die already!), and you want to write some tests to prove (and then resolve) the bug. To run your spec inside a web browser, simply load the HTML fixture associated with the spec (e.g., “test/javascripts/fixtures/graphics.html” for the tests in “graphics_spec.js”) and see the results of running the tests in that specific browser.

Check out the README for more information on the directory layout and a detailed description of the various Blue Ridge components.

jQuery-Opinionated

Blue Ridge wouldn’t quite fit into the Rails ecosystem if it didn’t come equipped with a few opinions. So by default, it assumes you’re using jQuery. “application_spec.js”, which was generated when you installed the plugin, includes an example of calling jQuery functions inside a test.

  require("spec_helper.js");
  require("../../public/javascripts/application.js");

  Screw.Unit(function() {
    describe("Your application javascript", function() {
      it("provides cliché example", function() {
        expect("hello").to(equal, "hello");
      });

      it("accesses the DOM from fixtures/application.html", function() {
        expect($('.select_me').length).to(equal, 2);
      });
    });
  });

And, no, we don’t actually encourage you to write tests for standard libraries like JQuery and Prototype; it just makes for an easy demo.

Prototype-Friendly

If you prefer Prototype, no problem: “Have it your way.”

  jQuery.noConflict();

  require("spec_helper.js");
  require("../../public/javascripts/prototype.js", {onload: function() {
      require("../../public/javascripts/application.js");
  }});

  Screw.Unit(function() {
      describe("Your application javascript", function() {
          it("accesses the DOM from fixtures/application.html", function() {
              expect($$('.select_me').length).to(equal, 2);
          });
      });
  });

Put jQuery into “no conflict” mode to give the `$` function back to Prototype, require `prototype.js`, and chain any files that are dependent on `prototype.js` in the `onload` callback. Done. Your Prototype-based tests await you.

Act Now, and We’ll Throw in Mocking Support

Blue Ridge includes Smoke, a JavaScript mocking and stubbing toolkit somewhat similar to Mocha. Assume we’re testing a function called `calculateTotalCost`, and you want to ensure that it calls `calculateComponentPrice` for each given component. That test might look something like so:

  it("calculates the total cost of a contract by adding the prices of each component", function() {
    var componentX = {}, componentY = {};
    mock(SalesContract).should_receive("calculateComponentPrice")
      .with_arguments(componentX).exactly(1, "time").and_return(42);
    mock(SalesContract).should_receive("calculateComponentPrice")
      .with_arguments(componentY).exactly(1, "time").and_return(24);
    expect(SalesContract.calculateTotalCost([componentX, componentY])).to(equal, 66);
  });

Fun with TextMate

Running individual specs from the command line is an essential feature, but if you use TextMate like we do, you’d rather not have to leave your editor in order to run a spec. If this describes your development style, take the Blue Ridge TextMate Bundle for a spin.

  cd ~/Library/Application Support/TextMate/Bundles/
  git clone git://github.com/karnowski/blue-ridge-tmbundle.git Blue\ Ridge.tmbundle

Once you reload your bundles (or restart TextMate), just hit Command-R to run the currently-open spec directly from TextMate.

And be sure to check out the snippets as well. Type `it`, `des`, `bef`, or `aft`, and then press the tab key to expand into full `it` blocks, `describe` blocks, etc.

But Wait, There’s More

Want more examples? To see Blue Ridge in action inside a working Rails app, check out the Blue Ridge sample application. Among other things, the sample app includes examples of:

  • using nested `describe` functions
  • setting up per-spec HTML “fixtures”
  • stubbing and mocking functions
  • running the Blue Ridge specs as part of your default Rake task

Money Back Guarantee

Blue Ridge is guaranteed to be bug free and fulfill your every need, or your money back! Of course, in lieu of a full refund, you’re welcome to hop over to the project’s GitHub issue tracker to let us know about any issues or ideas for possible improvements. Even better, fork the repo and start hacking! If you have patches, send us pull requests.

Now, go forth and give your JavaScript code the testing love it deserves!

Apr 30 2009

Comments

JavaScript Testing at RailsConf

Jason and I will be at RailsConf next week speaking about Blue-Ridge, our Rails plugin that makes test-driven JavaScript development easy and natural!

Here's our abstract: > Learn how to enjoy the benefits of test-driven development beyond just your Ruby on Rails code.  JavaScript is code too, and it deserves tests! With the help of some handy plugins, Rails lets you test your unobtrusive JavaScript using tools such as Screw.Unit and Smoke. The tools and approach are library-agnostic; they work well with jQuery, Prototype, and others.

The talk is at 1:50 PM on Tuesday, May 5. Come check it out, and give your JavaScript code the testing love it deserves.

Popular Tags