---
title: Jasmine and Shared Examples
teaser:
tags: web,javascript,testing
author: Josh Clayton
published_on: 2011-08-31
---

I've been doing a bit more Javascript development as of late and am using
Jasmine for my unit tests. It's been wonderful. I did find that it was a bit
of a bear to test shared behavior (there's a couple levels of inheritance in
the Backbone models) so I decided to whip up a crude implementation of shared
behavior.

    appNamespace.jasmine.sharedExamples = {
      "rectangle": function() {
        it("has four sides", function() {
          expect(this.subject.sides).toEqual(4);
        });
      },

      "square": function() {
        it("has the same width and height", function() {
          expect(this.subject.width).toEqual(this.subject.height);
        });
      },

      "an object with area": function(options) {
        it("calculates area correctly", function() {
          expect(this.subject.area()).toEqual(options.area);
        });
      }
    };

I've declared a handful of shared examples in an object I've made available to
my Jasmine suite. Next, to define `itShouldBehaveLike`:

    window.itShouldBehaveLike = function() {
      var exampleName      = _.first(arguments),
          exampleArguments = _.select(_.rest(arguments), function(arg) { return !_.isFunction(arg); }),
          innerBlock       = _.detect(arguments, function(arg) { return _.isFunction(arg); }),
          exampleGroup     = appNamespace.jasmine.sharedExamples[exampleName];

      if(exampleGroup) {
        return describe(exampleName, function() {
          exampleGroup.apply(this, exampleArguments);
          if(innerBlock) { innerBlock(); }
        });
      } else {
        return it("cannot find shared behavior: '" + exampleName + "'", function() {
          expect(false).toEqual(true);
        });
      }
    };

This uses a handful of Underscore.js functions to slice and dice arguments and
expects our `appNamespace.jasmine.sharedExamples` object to exist.

This checks to see that our example group exists, and if it doesn't, it
creates a failing test case warning us about it. If the example group _does_
exist, it'll wrap the behavior in a describe block (the property of the object
being the describe string), pass any additional arguments, and finally execute
any additional block of code.

Based on the shared examples above, we could write:

    describe("shapes", function() {
      describe("rectangle", function() {
        beforeEach(function() {
          this.subject = new Rectangle({ width: 5, height: 10 });
        });

        itShouldBehaveLike("rectangle");
        itShouldBehaveLike("an object with area", { area : 50 });
        itShouldBehaveLike("square", function() {
          beforeEach(function() {
            this.subject.set({ width: this.subject.height });
          });
        });
      });

      describe("square", function() {
        beforeEach(function() {
          this.subject = new Rectangle({ width: 5, height: 5 });
        });

        itShouldBehaveLike("rectangle");
        itShouldBehaveLike("an object with area", { area : 25 });
        itShouldBehaveLike("square");
      });
    });

What have you written to make unit-testing Javascript easier?
