QUnit is an easy to use testing framework* for an easy to test language. Once you've downloaded the library you can load up an .html page with all of your scripts, and the boilerplate qUnit HTML:
<h1 id="qunit-header">Validator Tests</h1> <h2 id="qunit-banner"></h2> <div id="qunit-testrunner-toolbar"></div> <h2 id="qunit-userAgent"></h2> <ol id="qunit-tests"></ol> <div id="qunit-fixture"> <input id="prefix_first" name="prefix.first" type="text" /> <input id="prefix_second" name="prefix.second" type="text" /> </div>
Notice we place two inputs inside of qunit-fixture. QUnit will position the qunit-fixture off screen so you'll never see this markup (and it won't interfere with your test output), but you can manipulate the elements inside the fixture from tests.
If we wanted to exercise our client validation script with tests, we could choose to isolate the "greaterdate" validation function that we wrote in the last post, and the tests might look something like this:
module("DateGreaterThan Tests", { setup: function () { this.greaterDate = jQuery.validator.methods["greaterdate"]; this.firstInput = $("#prefix_first"); this.secondInput = $("#prefix_second"); } }); test("Validation function is registered", function () { ok(this.greaterDate); }); test("Let empty values pass", function () { ok(this.greaterDate(this.firstInput.val(), this.firstInput[0], "second")); }); test("Let greater date pass", function () { this.firstInput.val("2/1/2011"); this.secondInput.val("12/12/2010"); ok(this.greaterDate(this.firstInput.val(), this.firstInput[0], "second")); }); test("Fail on equal date", function () { this.firstInput.val("2/1/2011"); this.secondInput.val("2/1/2011"); equals(this.greaterDate(this.firstInput.val(), this.firstInput[0], "second"), false); }); test("Fail on lesser date", function () { this.firstInput.val("2/1/2011"); this.secondInput.val("2/1/2012"); equals(this.greaterDate(this.firstInput.val(), this.firstInput[0], "second"), false); });
Notice you can use setup (and teardown) functions with QUnit, and QUnit will automatically reset the qunit-fixture.
* I have to admit when I look at some of the tests I see written with QUnit, I feel queasy inside. This mainly happens when I see the start and stop methods used for testing asynchronous code. I prefer hammet's approach of "Mock As You Wish".