QUnit 2.x Upgrade Guide


link Overview

This guide will assist in upgrading from QUnit 1.x to QUnit 2.x. All breaking changes are listed below, explaining how to upgrade your code to work with QUnit 2.x.

The qunit-migrate project can help you automate the transtions to QUnit 2.x.

Note that almost all the new APIs of QUnit 2.0.0 are already usable in QUnit 1.23.1, allowing you to migrate step by step. The only exception is the new module hooks before and after.

QUnit 2.0.x will include a migration layer that throws descriptive errors for all deprecated methods ("Global 'test()' method is removed, use 'QUnit.test() instead"), to help you migrate to the new APIs. QUnit 2.1+ will remove that layer, causing failures that will be more difficult to debug ("ReferenceError: test is not defined").

link Removed globals

QUnit no longer exposes multiple global variables. The only global variable still exposed is QUnit. Use QUnit.module() and QUnit.test() to define your testsuite, and use the assert argument in test callbacks to write assertions.

The global stop() and start() methods are gone, replaced by assert.async(), which returns a callback. Execute this callback when your test is done.

link Replace module() with QUnit.module()

The global function module() is gone. Use QUnit.module() instead.

Before:

1
module( "router" );

After:

1
QUnit.module( "router" );

link Replace test() with QUnit.test()

The global function test() is gone, use QUnit.test() instead.

Before:

1
test( "defaults to home" );

After:

1
QUnit.test( "defaults to home" );

link Replace asyncTest() with QUnit.test() and assert.async()

The global function asyncTest() is gone. Use QUnit.test() and assert.async() instead.

Before:

1
2
3
4
5
6
asyncTest( "navigates to new page (async)", function( assert ) {
router.navigate(function( newPage ) {
assert.equal( newPage.id, 1 );
start();
})
});

After:

1
2
3
4
5
6
7
QUnit.test( "navigates to new page (async)", function( assert ) {
var done = assert.async();
router.navigate(function( newPage ) {
assert.equal( newPage.id, 1 );
done();
})
});

link Replace stop() and start() with assert.async()

The global functions stop() and start() are gone. Use assert.async() instead, which returns a "done" function that should be called when the asynchronous operation has completed.

Before:

1
2
3
4
5
6
7
QUnit.test( "navigates to new page (async)", function( assert ) {
stop();
router.navigate(function( newPage ) {
assert.equal( newPage.id, 1 );
start();
})
});

After:

1
2
3
4
5
6
7
QUnit.test( "navigates to new page (async)", function( assert ) {
var done = assert.async();
router.navigate(function( newPage ) {
assert.equal( newPage.id, 1 );
done();
})
});

link Replace expect() with assert.expect()

The global function expect() is gone. Use assert.expect() instead.

Before:

1
2
3
4
5
6
QUnit.test( "refresh (sync)", function( assert ) {
expect( 1 );
router.refresh(function( currentPage ) {
assert.equal( currentPage.id, 2 );
});
});

After:

1
2
3
4
5
6
QUnit.test( "refresh (sync)", function( assert ) {
assert.expect( 1 );
router.refresh(function( currentPage ) {
assert.equal( currentPage.id, 2 );
});
});

link Replace global assertions with assert arguments

All global assertions, like equal() and deepEqual() are gone. Use assert instead, like assert.equal() or assert.deepEqual().

Here are all assertion methods affected by this change in alphabetic order: deepEqual(), equal(), notDeepEqual(), notEqual(), notPropEqual(), notStrictEqual(), ok(), propEqual(), strictEqual(), throws().

Before:

1
2
3
4
5
6
7
8
QUnit.test( "static properties", function() {
ok( router.initialized );
equal( router.currentPage.id, 3 );
deepEqual( router.currentPage, {
id: 3,
path: "/about"
});
});

After:

1
2
3
4
5
6
7
8
QUnit.test( "static properties", function( assert ) {
assert.ok( router.initialized );
assert.equal( router.currentPage.id, 3 );
assert.deepEqual( router.currentPage, {
id: 3,
path: "/about"
});
});

link Rename module hooks

The module hooks setup and teardown have been renamed to beforeEach and afterEach, to make it more obvious that they run for each test within a module.

Before:

1
2
3
4
5
6
7
8
QUnit.module( "router", {
setup: function( assert ) {
this.router = new Router();
},
teardown: function( assert ) {
this.router.destroy();
}
});

After:

1
2
3
4
5
6
7
8
QUnit.module( "router", {
beforeEach: function( assert ) {
this.router = new Router();
},
afterEach: function( assert ) {
this.router.destroy();
}
});

link Replace assert.throws( block, string, message ) with assert.throws( block, regexp, message )

The overload of assert.throws() which expected a block, error string, and assertion message has been removed and will now throw an exception. Use a regular expression instead.

Before:

1
2
3
4
5
QUnit.test( "throws", function( assert ) {
assert.throws( function() {
throw new Error( "This is an error" );
}, "This is an error", "An error should have been thrown" );
});

After:

1
2
3
4
5
QUnit.test( "throws", function( assert ) {
assert.throws( function() {
throw new Error( "This is an error" );
}, /^This is an error$/, "An error should have been thrown" );
});

Note that in the two-argument overload assert.throws( block, string ), the string argument has always been interpreted as an assertion message instead of an expected value. You do not need to change any of these assertions. Of course, you should use the assert.throws( block, regexp, message ) form anyway to make your assertions more precise.

link Removed and modified QUnit methods and properties

A few methods and properties in the QUnit namespace have been modified or removed.

link Replace QUnit.log = callback with QUnit.log( callback ) for all reporting callbacks

For several versions of QUnit before 2.0, custom reporters could be registered by calling the appropiate methods with a callback function. If your code still uses the old approach of overwriting a property on the QUnit object, replace that by calling the method instead.

This applies to all reporting callbacks, specifically: begin, done, log, moduleDone, moduleStart, testDone, testStart.

Before:

1
2
3
QUnit.log = function( results ) {
console.log( results );
};

After:

1
2
3
QUnit.log(function( results ) {
console.log( results );
});

link Replace QUnit.push() with this.push()

To implement custom assertions, assign functions to QUnit.assert, inside use this.push(), replacing QUnit.push. This way, the assertion will be directly related to its test context, preventing asynchronous tests leaking assertions to other tests.

Before:

1
2
3
4
QUnit.assert.mod2 = function( value, expected, message ) {
var actual = value % 2;
QUnit.push( actual === expected, actual, expected, message );
};

After:

1
2
3
4
QUnit.assert.mod2 = function( value, expected, message ) {
var actual = value % 2;
this.push( actual === expected, actual, expected, message );
};

link Stop using QUnit.init, no replacement

This method used to reinitialize the test runner. It should never have been exposed as a public method and is now gone, without replacement. If you've built a setup that requires the use of QUnit.init, contact us (issue tracker, forum, IRC) and we can recommend a replacement.

link Stop using QUnit.reset, split one test into multiple tests

This method used to give access to QUnit's internal fixture reset. This is now gone, without replacement. If your code is using it, you probably need to split affected tests into multiple tests.

Before:

1
2
3
4
5
6
7
8
9
10
QUnit.test( "refresh", function( assert ) {
router.refresh();
assert.equal( router.currentPage.id, 1 );
QUnit.reset();
history.replaceState( "/about" );
router.refresh();
assert.equal( router.currentPage.id, 2 );
});

After:

1
2
3
4
5
6
7
8
9
10
QUnit.test( "refresh, default", function( assert ) {
router.refresh();
assert.equal( router.currentPage.id, 1 );
});
QUnit.test( "refresh, after replaceState", function( assert ) {
history.replaceState( "/about" );
router.refresh();
assert.equal( router.currentPage.id, 2 );
});

link Replace QUnit.jsDump with QUnit.dump

Originally jsDump was a standalone library imported into QUnit. It has since evolved further within the library. To reflect that, the property was renamed to QUnit.dump.parse. This should only affect custom reporter code, not regular testsuites.

Before:

1
2
3
4
5
QUnit.log(function( obj ) {
var actual = QUnit.jsDump.parse( obj.actual );
var expected = QUnit.jsDump.parse( obj.expected );
sendMessage( obj.result, actual, expected );
});

After:

1
2
3
4
5
QUnit.log(function( obj ) {
var actual = QUnit.dump.parse( obj.actual );
var expected = QUnit.dump.parse( obj.expected );
sendMessage( obj.result, actual, expected );
});

link Replace expected argument in QUnit.test

The optional second expected argument that QUnit.test used to accept was removed. Call assert.expect() instead.

Before:

1
2
3
QUnit.test( "addition", 1, function( assert ) {
assert.equal( add( 1, 2 ), 3 );
});

After:

1
2
3
4
QUnit.test( "addition", function( assert ) {
assert.expect( 1 );
assert.equal( add( 1, 2 ), 3 );
});