With a blog entitled "Agile Ajax," I figure it was time to finally address a topic on Agile development. One of my favorite agile techniques is Test Driven Development (TDD). It's micro rather than macro, i.e. it's at the level of the individual developer rather than the team. As a tech lead, I take great delight in scratching my head and asking developers "where's the unit test?" After a while, they learn that it's better to write the unit test up front rather than slapping it together at the end. If a developer consistently skips the unit tests, he's looking for a new job.
Some of the benefits of TDD? The quality of the code improves, the productivity of continuous integration tools like CruiseControl is multiplied, and developers spend more time implementing and less time debugging. In the case of Javascript and AJAX, where different version of browsers running on different operation systems can have a big impact on if and how your code works, having automated unit tests can save you a ton of time.
First, let's clear up some confusion. There are two JsUnit projects, both claiming to be ports of JUnit to Javascript. I've only used the one developed by Edward Hieatt at jsunit.net, so that is the one I'll be discussing. If you're not already familiar with JUnit and TDD, I'd suggest reading this gentle introduction over at the JUnit project.
So JsUnit does for Javascript what JUnit does for Java. Let's produce a simple example, namely something that works in certain versions of browsers, but not others. We'll pick new Date().getYear()
which will display a four digit year in IE and the ECMAScript standard year-1900 in Firefox. Here is our sample JsUnit test.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JsUnit Browser Date Diff Tests</title>
<script language="JavaScript" type="text/javascript" src="jsUnitCore.js"></script>
<script language="JavaScript" type="text/javascript">
// Test the date stuff
function testDateGetYear() {
var date = new Date();
debug("getYear() gives value ", date.getYear());
debug("getFullYear() gives value ", date.getFullYear());
assertNotEquals("ECMAScript error", date.getYear(), date.getFullYear());
}
function testCalcDateGetYear() {
var date = new Date();
debug("getYear() gives value ", date.getYear());
debug("getFullYear() - 1900 gives value ", date.getFullYear() -1900);
assertEquals("ECMAScript error", date.getYear(), date.getFullYear()-1900);
}
</script>
</head>
<body>
<h1>JsUnit Browser Date Diff Tests</h1>
<p>This page contains tests for the JsUnit Browser Date Diff
tests. To see them, take a look at the source.</p>
</body>
</html>
Each test case is contained in an HTML file and each function that begins with "test" is a test. The info, warn and debug commands let you write out informational messages without having to do annoying alert boxes. You may need to change the location of the core JsUnit file jsUnitCore.js, depending on where you've placed it. JsUnit comes with a test runner, much like JUnit. If you've installed JsUnit in C:/jsunit
, then the browser is at C:/jsunit/testRunner.html
. Load this file in your browser, browser for your test file and click Run. If you're using Firefox, you'll see something like this (seen here with the trace popup window already closed):
If you're using IE, you'll see something like this:
And if you drill down into the individual errors, you'll see something like this:
There's a whole lot more to JsUnit than what we've seen. You can bunch together lots of test cases into suites. You can automate the running of tests using ant and a simple embedded HTTP Server. This setup will even let you automatically run the JsUnit tests in browsers on remote machines. That way you can test on all possible combinations of browsers and OS's. If you've ever tried to verify browser compatibility in your Javascript, you know how sweet this is.
These unit tests could even be used as a quick helpdesk or field regression tool. Client hassling you about a broken app? Have them run the unit tests in their browser, then read the errors from the JsUnit server logs. You'll track down that annoying Firefox Rhino plugin in no time flat.
If you plan on doing any serious Javascript development, I heartily recommend this tool. You may end up modify it to suit your needs or rolling your own, but it is an excellent place to start. And remember: test first!