Blog Archives

Two new QUnit Test Types – Skipped and Interactive

I love unit testing, and the confident feeling I get from my code being “all green”. But sometimes there are tests that need to be skipped for a bit, perhaps due to a failing backend service or an in-progress refactoring. The easiest solution is to comment them out, but then it’s easy to forget they are being skipped. Instead, I simply added a new test type – testSkip – to QUnit using the following code. Now when the test is skipped we see it marked as SKIPPED in the QUnit results.


QUnit.testSkip = function() {
   q.test(arguments[0] + " (SKIPPED)", function() {});
};

I use a similar approach for QUnit tests that involve user interaction. I run lots of tests when coding, but the interactive ones get in the way of my flow. So I have added the test type testManual which allows me to run them explicitly by simply adding testmanual to the URL parameters. A similar approach can be used for other test categories or to target tests to a particular browser.


QUnit.testManual = function() {
   if(/(\?|&)testmanual($|&|=)/.test(window.location.href)) {
      q.test.apply(q, arguments);
   } else {
      q.testSkip.apply(q, arguments);
   }
};

Advertisements

A bindOnce event listener for Backbone.js

I’m going to guess you are familiar with Backbone, the MVC framework of choice for many web developers. I use Backbone a fair amount for its Model and Event aspects both because it works and it’s often what others expect.

But there is one feature I miss with Backbone event handling – the ability to listen for an event once (like jQuery’s once). You can write your own code to simply ignore later events, but the event handling code is still there.  It would be better to unbind, but with Backbone that means holding on to the callback function so you can unbind it on the first callback, and to do that you have to assign your callback to a variable which can clutter up simple event handling code.

Or you can just write a bindOnce function that does that for you which is what I did. I feel like this should be a standard feature, so I’ve packaged it up with some tests and submitted it to the Backbone folks in pull request 663. Usage is simple and looks like this:

obj.bindOnce('event', function(){
   obj.counterA += 1;
});

Update 10/29/11

Wow, that was quick. My bindOnce is now part of Backbone with the updated name of once (which makes sense since it matches jQuery). It always speeds things up when you include the tests :)

Adding a little jQuery/Sizzle to FirePath for Firebug

FirePath is a very cool Firebug plugin that adds the ability to search the HTML tree using XPath or CSS Selectors. It filters the actual Firebug DOM tree so you can then act on that element in all the normal Firebug ways (view DOM, inspect, etc).

Here is a screenshot:

Unfortunately FirePath only supports native CSS Selectors, and most of the world (including me) actually uses jQuery’s Sizzle which gives us some really key additions like :not, :contains, and :first.

So I did a little extension hacking and added Sizzle support to FirePath. You can find the patch for it where I submitted it to the FirePath author at http://code.google.com/p/firepath/issues/detail?id=22.

Update 3/22/2011

I guess I’m not the only one who wanted to use jQuery/Sizzle. The patch was accepted and FirePath with jQuery/Sizzle is now available in Version 0.9.6.1!

Logging QUnit results

I’ve mentioned QUnit in other posts [POST: CUSTOM QUNIT TEST TYPES] and how much stock I put into unit testing in general, so I thought I’d share some more tips for people who don’t have much experience with QUnit. This will probably be a recurring theme on this blog.

One of the advantages of QUnit is that it has built-in hooks for testing automation tools. I use these hooks to do basic console logging so I can see what test is running next to my own log messages. I also log the amount of time each test takes.

The code to add these hooks is straightforward:

var startTime = null;
var currentTest = null;
QUnit.testStart = function(details) {
   currentTest = details.name;
   startTime = new Date().getTime();
   console.warn("QUnit starting " + currentTest);
};

QUnit.testDone = function(details) {
   console.assert(currentTest);
   cm.console.warn("QUnit finished " + currentTest + " (" + (new Date().getTime() - startTime).toString() + " ms)");
   currentTest = null;
};

QUnit.begin = function(details) {
   cm.console.log("QUnit starting");
};

QUnit.done = function(details) {
   cm.console.log("QUnit finished");
};

If you use modules then there are hooks at that level also:

QUnit.moduleStart = function(details) {
};
QUnit.moduleDone = function(details) {
};

The same approach can be used to do other things like send notifications (email/tweet) or generate a timing summary. You can read more about the QUnit integration hooks at:
http://docs.jquery.com/Qunit#Integration_into_Browser_Automation_Tools.

%d bloggers like this: