DailyJS

JavaScript Unit Testing

Alex R. Young

Subscribe

@dailyjs

Facebook

Google+

libraries testing

JavaScript Unit Testing

Posted by Alex R. Young on .
Featured

libraries testing

JavaScript Unit Testing

Posted by Alex R. Young on .

Our JavaScript Developer Survey
results
showed that a
large percentage of readers don't currently unit test their JavaScript.
I've been unit testing my own JavaScript projects for a few years, which
resulted in the creation of
riotjs -- for more on riotjs see my blog post: Riotjs: A JavaScript Unit Testing
Framework

There are lots of JavaScript test frameworks. I've presented a summary
below -- there are both traditional unit testing libraries and
behaviour-driven frameworks.

unittest.js

unittest.js by Thomas Fuchs has been used by many JavaScript developers since
Scriptaculous became popular in 2006. It provides a test framework that is recognisable to Ruby developers, and
the relationship between Rails and Scriptaculous further increased
adoption in this group.

This library depends on Prototype and is
usually run inside HTML templates rather than a JavaScript interpreter.

Tests look like this:

  new Test.Unit.Runner({
    testExample: function() { with(this) {
      var exampleVar = '1234';
      assertEqual('1234', exampleVar);
      assert(true);
    }}

  }, "testlog");

Fuchs uses with(this) to cut down unnecessary syntax -- you
don't have to write tests this way though.

Setup and teardown methods are supported. Shoulda-style assertion names
have also been added. This adds methods to the prototypes for common
JavaScript objects, so it's possible to write
'test'.shouldEqual('test').

unittest.js also includes a handy benchmark method, and the
following assertions:


assertNotEqual(expected, actual) Inverse of assertEqual assertNotVisible(element) Checks if an element has display: none assertVisible(element) Inverse of above assertInspect(expected, actual) Checks if expected is the same as actual.inspect() assertEnumEqual(expected, actual) Ensured two enumerables are equal assertIdentical(expected, actual) Comparison using === assertNotIdentical(expected, actual) Inverse of above assertNull(obj) Is obj null? assertNotNull(obj) Inverse of above assertMatch(expected, actual) Performs a regex, where expected is the regex assertType(expected, actual) Checks if actual.constructor == expected assertNotOfType(expected, actual) Inverse of above assertInstanceOf(expected, actual) Checks if actual is instanceof expected assertNotInstanceOf(expected, actual) Inverse of above assertRespondsTo(method, obj) Checks if obj has a method named method assertReturnsTrue(method, obj) Ensured that the method named method called on obj returns true assertReturnsFalse Inverse of above assertRaise(exceptionName, method) Ensures calling method raises an exception named exceptionName assertElementsMatch([elements], expression1, expression2, ...) Ensures the array of elements match the list of expressions assertElementMatches(element, expression) A helper for the above assertion when supplying a single element


JsUnitTest

JsUnitTest is a port of unittest.js without the Prototype dependency.

JsUnit

Development for JsUnit started in 2001, and is
based on JUnit. Like unittest.js, tests are designed to be run in a web
browser. By using the build.xml Ant file, tests can be run
against multiple browsers on a local machine, or on multiple remote
machines.

JsUnit tests are grouped within a Test Page. Test pages contain your
tests. If a Test Page has setUp or tearDown
functions, they will be run before and after each test function. A
function called setUpPage will be run once per Test Page.

Each test function is written prefixed with test:

function testExample() {
    assert(true);
}

The following assertions are available:

  • assert([comment], booleanValue)
  • assertTrue([comment], booleanValue)
  • assertFalse([comment], booleanValue)
  • assertEquals([comment], value1, value2)
  • assertNotEquals([comment], value1, value2)
  • assertNull([comment], value)
  • assertNotNull([comment], value)
  • assertUndefined([comment], value)
  • assertNotUndefined([comment], value)
  • assertNaN([comment], value)
  • assertNotNaN([comment], value)
  • fail(comment)

QUnit

QUnit is used by jQuery for its unit tests. To use QUnit, include qunit.js and qunit.css within a HTML file
that can display the test results.

Tests look like this:

test("a basic test example", function() {
  ok(true, "this test is fine");
  var value = "hello";
  equals("hello", value, "We expect value to be hello");
});

The jQuery QUnit documentation has full
examples.

jspec

jspec (by Yehuda Katz) is an RSpec inspired framework. Rather than traditional unit tests, jspec attempts to provide a behaviour-driven development
approach.

This is best illustrated with an example:

jspec.describe("The browser environment", function() {
  it("should have Array.prototype.push", function() {
    Array.prototype.push.should("exist");
  });

  it("should have Function.prototype.apply", function() {
    Function.prototype.apply.should("exist");
  });
})

Tests are written with it() blocks and chained
should() calls.

The GitHub repository is currently pretty spartan, with no documentation
or README, but jspec is a good port for those of you who are familiar
with RSpec or want a change from JUnit-style libraries.

JSpec

JSpec by visionmedia (who have cropped up frequently on DailyJS) is a much more fleshed out BDD
library. The author has tried to keep it minimal, but it has a unique
and friendly DSL. It's possible to write "grammar-less" tests using
plain JavaScript.

Jasmine

Jasmine builds on the ideas of the previous libraries to provide a BDD library that supports asynchronous
tests -- Ajax-friendly testing.