Unit Testing JavaScript with QUnit

iseven_test

For a recent project I had to dig into my JavaScript past and work on some cross platform, enterprise level client side coding. Luckily I still remember most things, but it’s been interesting seeing the changes in the platform since I last used it extensively a couple of years ago. First step was digging up the old JavaScript unit testing frameworks I’d used, such as jsUnit. Then I remembered what a giant pain in the but jsUnit is to get working. Too many path issues, dependencies, etc.

My requirements for a testing framework are:

  • easy to setup
  • dependency free
  • simple xUnit style tests and assertions
  • runs in most browsers
  • allows my tests to be in their own js files

I was happy to discover that in my absence a very nice little testing framework has evolved. It’s called QUnit, and is used by the jquery folks for unit testing their code and is available at the QUnit GitHub Repository. It’s only got two files as dependencies, and you can load those off of the web if you’d like. It has an xUnit syntax, can work with or without the DOM, and has a super simple async testing strategy.

The test runner is basically a simple HTML page (you can make your own, or just copy their example), to which you simply include your tests as javascript src files. The API is well documented, but here’s some example tests from some code I’m testing to parse google search terms out of the referrer URL of a page.

For example,:

test("google: single word", function() {
    var r = util.getSearchEngineKeywords("http://www.google.com/search?hl=en&source=hp&biw=1082&bih=1245&q=boone&aq=f&aqi=g10&aql=&oq=");
    equal(r.searchEngine, "google", "verify search engine");
    deepEqual(r.terms, ["boone"], "verify terms");
});

test("google: multiple words", function() {
    var r = util.getSearchEngineKeywords("http://www.google.com/search?hl=en&biw=1082&bih=1245&q=Daniel+Boone&aq=f&aqi=g-s1g-sx9&aql=&oq=");
    equal(r.searchEngine, "google", "verify search engine");
    deepEqual(r.terms, ["Daniel", "Boone"], "verify terms");
});

test("google: quoted words", function() {
    var r = util.getSearchEngineKeywords("http://www.google.com/search?hl=en&biw=1082&bih=1245&q=%22Daniel+Boone%22+tracker&aq=f&aqi=&aql=&oq=");
    equal(r.searchEngine, "google", "verify search engine");
    deepEqual(r.terms, ["Daniel Boone", "tracker"], "verify terms");
});

Async tests are simple too. You just create an asyncTest, which pauses the test runner, set some timeouts, then inform the test runner when to start back up after you completed your assertions. For example, here’s a test from a session library I’m writing that verifies that 5 seconds later asking for a session gives you the same session id back.

asyncTest("default session timeout is long lived", function() {
    var session = new Session({ reset:true });
    setTimeout(function() {
        var newSession = new Session();
        equal(newSession.visitorId, session.visitorId, "visitor ids should match");
        equal(newSession.sessionId, session.sessionId, "session ids should match");
        start();
    }, 5000);
});

Here’s a link to a great QUnit tutorial, rather than writing something more detailed up myself.

Slow Motion iPhone/iPad Simulator

If you are trying to develop a particular complex animation, use this trick to turn on “slow motion mode” in the simulator. It’ll be much easier to see what’s going on.

Start the simulator as normal. next, make sure you enable “simulate hardware keyboard” in the simulator’s hardware menu, and then press your Mac’s shift key 3 times in rapid succession to toggle it on/off. You’ll see in the debugger that slow motion mode has been activated. Press the shift key 3 more times to toggle it off.

How to backup remote disks with Time Machine

I quite like Time Machine, the backup solution built into Mac OSX. I also like remote network drives like iDisk or Amazon S3 solutions. Unlike DropBox however (another great service), these drives don’t necessarily store copies of their files locally, and are therefore not backed up. In the case of iDisk, the sparsebundle image IS backed up, but that’s not really what I want. I want file level access to previous revisions of files.

So, I’ve set up a cron job which runs every hour and pulls down any updates. Very simple:

rsync -a --delete --update --whole-file /Volumes/iDisk/ /Users/duane/Backups/iDisk/

Creating iPhone UI Mockups

When I begin designing a new iPhone application, I always start with simple wireframes. I prefer to first build my user interfaces as low-fidelity wireframe sketches, rather than more realistic images of user interfaces.

I have found that during the early phases of the project sketchy, low-fidelity wireframes better focus the conversation on functionality, rather than visual design. Otherwise, it’s easy to go down the “font and color selection rathole”. This is particularly the case when working with clients.

Low fidelity wireframes, by eschewing many cosmetic factors, are also faster to create and modify and thus allow me to quickly tackle fundamental issues regarding the usability of your interface. Suggestions and refinements can quickly be incorporated for further fine tuning.

Adopting a user centered design philosophy by first focusing on the usability and interactivity of your interface before applying a visual design provides you with a solid foundation for great design rather than having a pretty, but unwieldy, visual design long set in stone that must be expensively remodeled.

I’ve used a number of tools, but my recent favorite is the wonderful Balsamiq Mockups It’s an Adobe Air application, but don’t hold that against it, it works great on the Mac.

My favorite features are probably the wiki-style text markup for quickly laying out table views, and the ability to easily export selections to the clipboard as PNG images for easy pasting into presentations and documents.

Tagged: ,

An Excellent Approach to Branch Management

I’ve had several colleagues recommend an approach to managing development and release branches using git from Vincent Driessen in his blog post A Successful Git Branching Model.

A Successful Git Branching Model

I’ve been using it myself a few weeks myself (though admittedly not on a release system) and it feels correct to me. It is similar to approaches I’ve used in the past with CVS and SVN. The approach is not particular novel or remarkable necessarily, but the post is very detailed and very well explained, to the the point it’s a great thing to point to as a standard process. I plan to use it on all my production projects.

There is also a project on github called git-flow that provides a high-level set of operations to mimic this workflow. It is described in the blog post Why aren’t you using git-flow from Jeff Kreeftmeijer. I have’n used it myself yet.

iPhone Blogs I Follow

A colleague recently asked me for a list of iPhone development blogs that I read. Here’s some sites whose RSS feeds I follow regularly:

A Clean Slate…

cleanslate

I recently decided to reset my blog and start from scratch. Even though there was 10 or more years of postings here, I’ve historically been an infrequent poster so it didn’t amount to much.

The effort to move everything forward just wasn’t justified. I mean, if you really need the power points slide from a talk I gave on JavaScript in at a Netscape Developer’s Conference in 1998, well, I’m sorry.

That being said, if you came here looking for something that was actually useful, I do have all the old data and will move things back online as necessary.