This guide will assist you in upgrading from QUnit 1 to QUnit 2.
Overview
The QUnit 2 release only removes old methods. The “QUnit 2” methods were introduced as part of QUnit 1.x releases. If you are on QUnit 1.23, you can already migrate gradually, before making the jump.
The old methods are removed in QUnit 2.0 and replaced with placeholder methods that throw descriptive errors to simplify migration ("Global 'test()' method is removed, use 'QUnit.test() instead"
). QUnit 2.1 removes that layer and would instead throw native errors like "ReferenceError: test is not defined"
.
QUnit 1.x | QUnit 2.x |
---|---|
module() |
QUnit.module() |
test() |
QUnit.test() |
asyncTest() |
QUnit.test() with assert.async() |
stop() /start() |
assert.async() |
expect() |
assert.expect() |
ok() , equal() , deepEqual() , … |
assert |
setup /teardown options |
beforeEach and afterEach hooks |
For plugins and other integrations:
QUnit 1.x | QUnit 2.x |
---|---|
QUnit.log = … QUnit.begin = … … |
QUnit.log(…) ,QUnit.begin(…) ,… |
QUnit.push() |
assert.pushResult() |
QUnit.jsDump.parse() |
QUnit.dump.parse() |
Changes
The qunit-migrate tool can automate the transition to QUnit 2.
- Removed global functions
- Introducing
assert.async
- Renamed module hooks
- Removed legacy callback properties
- Replace
QUnit.push
withassert.pushResult
- Removed
QUnit.init
without replacement - Removed
QUnit.reset
- Renamed
QUnit.jsDump
toQUnit.dump
- Replace
expected
number argument ofQUnit.test
- Replace
assert.throws(Function, string, message)
signature
Removed global functions
QUnit 2 no longer uses global functions. The main methods are now part of the QUnit
interface, and the assertion methods are exposed through a new assert
object that is bound to each test.
Before:
module('example');
test('add', function () {
equal(add(2, 3), 5);
});
After:
QUnit.module('example');
QUnit.test('add', assert => {
assert.equal(add(2, 3), 5);
});
Introducing assert.async()
Use assert.async()
instead of the stop()
and start()
functions. Calling assert.async()
returns a done
function that should be called once the asynchronous operation is finished.
Similarly, if you were using asyncTest()
, use the regular QUnit.test()
with assert.async()
instead.
Before:
QUnit.test('navigates to new page', function () {
stop();
router.navigate(function (newPage) {
equal(newPage.id, 1);
start();
});
});
// Or
asyncTest('navigates to new page', function () {
router.navigate(function (newPage) {
equal(newPage.id, 1);
start();
});
});
After:
QUnit.test('navigates to new page', assert => {
const done = assert.async();
router.navigate(newPage => {
assert.equal(newPage.id, 1);
done();
});
});
Renamed module hooks
The module hooks setup
and teardown
have been renamed to beforeEach
and afterEach
. The new names were first introduced in QUnit 1.16, and removed in QUnit 2.0.
Before:
QUnit.module('router', {
setup: function () {
this.router = new Router();
},
teardown: function () {
this.router.destroy();
}
});
After:
QUnit.module('router', {
beforeEach: () => {
this.router = new Router();
},
afterEach: () => {
this.router.destroy();
}
});
You can also use a module scope as of QUnit 1.20, which makes for simpler sharing of variables and associating of tests with modules.
Example:
QUnit.module('router', hooks => {
let router;
hooks.beforeEach(() => {
router = new Router();
});
hooks.afterEach(() => {
router.destroy();
});
QUnit.test('add', assert => {
assert.true(router.add('/about'));
});
});
Removed legacy callback properties
Early alpha releases of QUnit 0.x required property assignments to register callback events. In QUnit 1.0, these were deprecated in favour of more modern event registration methods. The ability to use assignments as way to register callbacks was removed in QUnit 2.0.
See also QUnit.on()
.
Before:
QUnit.log = function (results) {
console.log(results);
};
After:
QUnit.log(function (results) {
console.log(results);
});
This applies to all reporting callbacks, specifically: begin
, done
, log
, moduleDone
, moduleStart
, testDone
, and testStart
.
Replace QUnit.push()
with assert.pushResult()
To implement custom assertions, assign functions to QUnit.assert
, and inside use this.pushResult()
instead of QUnit.push
. This allows assertions to be directly associated with its test context, preventing asynchronous tests from leaking into other tests.
Before:
QUnit.assert.mod2 = function (value, expected, message) {
const actual = value % 2;
QUnit.push(actual === expected, actual, expected, message);
};
After:
QUnit.assert.mod2 = function (value, expected, message) {
const actual = value % 2;
this.pushResult({ result: actual === expected, actual, expected, message });
};
Removed QUnit.init
without 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 an integration or runner framework that requires the use of QUnit.init
, reach out in our Chat room, or contact us in the issue tracker to help find a replacement.
Removed QUnit.reset
This method accessed QUnit’s internal fixture reset. This is now gone, without replacement. If your code is using it, you may need to split affected tests into separate tests.
Before:
QUnit.test('currentPage', assert => {
router.refresh();
assert.equal(router.currentPage.id, 1);
QUnit.reset();
history.replaceState('/about');
router.refresh();
assert.equal(router.currentPage.id, 42);
});
After:
QUnit.test('currentPage default', assert => {
router.refresh();
assert.equal(router.currentPage.id, 1);
});
QUnit.test('currentPage after replaceState', assert => {
history.replaceState('/about');
router.refresh();
assert.equal(router.currentPage.id, 42);
});
Renamed QUnit.jsDump
to 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(obj => {
const actual = QUnit.jsDump.parse(obj.actual);
const expected = QUnit.jsDump.parse(obj.expected);
sendMessage(obj.result, actual, expected);
});
After:
QUnit.log(obj => {
const actual = QUnit.dump.parse(obj.actual);
const expected = QUnit.dump.parse(obj.expected);
sendMessage(obj.result, actual, expected);
});
Replace expected
number argument of QUnit.test
The optional expected
argument to QUnit.test
for specifying the expected number of assertions, was removed. Call assert.expect()
instead.
Before:
QUnit.test('addition', 1, assert => {
assert.equal(add(2, 3), 5);
});
After:
QUnit.test('addition', assert => {
assert.expect(1);
assert.equal(add(2, 3), 5);
});
Replace assert.throws(Function, string, message)
signature
The signature of assert.throws()
that accepted an error string as second parameter has been removed. This avoids ambiguity with the assertion message, as both parameters were optional.
It is recommended to use a regular expression or error object as the expected value instead.
For example, to test the following code:
function add (a, b) {
if (a === undefined) {
throw new Error('This is an error');
}
}
Before:
QUnit.test('add', assert => {
assert.throws(() => {
add();
}, 'This is an error', 'Fail if A is undefined');
});
After:
QUnit.test('add', assert => {
assert.throws(() => {
add();
}, /This is an error/, 'Fail if A is undefined');
});
// Or
QUnit.test('add', assert => {
assert.throws(() => {
add();
}, new Error('This is an error'), 'Fail if A is undefined');
});
See assert.throws()
for an overview of the supported signatures.
Note that in the two-argument signature assert.throws(Function, string)
has always been interpreted as asserting anything is thrown, with the string argument being the assertion message. This continues to be supported.