2.x Upgrade Guide

Overview

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

The qunit-migrate project can help you automate the transition 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").

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 test suite, 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.

Replace module() with QUnit.module()

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

Before:

module( "router" );

After:

QUnit.module( "router" );

Replace test() with QUnit.test()

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

Before:

test( "defaults to home" );

After:

QUnit.test( "defaults to home" );

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:

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

After:

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

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

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

Before:

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

After:

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

Replace expect() with assert.expect()

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

Before:

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

After:

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

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(), and throws().

Before:

QUnit.test( "static properties", function() {
	ok( router.initialized );
	equal( router.currentPage.id, 3 );
	deepEqual( router.currentPage, {
		id: 3,
		path: "/about"
	});
});

After:

QUnit.test( "static properties", function( assert ) {
	assert.ok( router.initialized );
	assert.equal( router.currentPage.id, 3 );
	assert.deepEqual( router.currentPage, {
		id: 3,
		path: "/about"
	});
});

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:

QUnit.module( "router", {
	setup: function( assert ) {
		this.router = new Router();
	},
	teardown: function( assert ) {
		this.router.destroy();
	}
});

After:

QUnit.module( "router", {
	beforeEach: function( assert ) {
		this.router = new Router();
	},
	afterEach: function( assert ) {
		this.router.destroy();
	}
});

Removed and modified QUnit methods and properties

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

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 appropriate 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, and testStart.

Before:

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

After:

QUnit.log(function( results ) {
	console.log( results );
});

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

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

Before:

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

After:

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

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.

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:

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:

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 );
});

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:

QUnit.log(function( obj ) {
  var actual = QUnit.jsDump.parse( obj.actual );
  var expected = QUnit.jsDump.parse( obj.expected );
  sendMessage( obj.result, actual, expected );
});

After:

QUnit.log(function( obj ) {
  var actual = QUnit.dump.parse( obj.actual );
  var expected = QUnit.dump.parse( obj.expected );
  sendMessage( obj.result, actual, expected );
});

Replace expected argument in QUnit.test

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

Before:

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

After:

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

Miscellaneous

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:

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:

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.