layout | title | excerpt | groups | redirect_from | version_added | ||||
---|---|---|---|---|---|---|---|---|---|
page-api |
QUnit.module() |
Group related tests under a common label. |
|
|
1.0.0 |
QUnit.module( name )
QUnit.module( name, nested )
QUnit.module( name, options )
QUnit.module( name, options, nested )
Group related tests under a common label.
parameter | description |
---|---|
name (string) |
Label for this group of tests. |
options (object) |
Set hook callbacks. |
nested (function) |
A scope to create nested modules and/or add hooks functionally. |
All tests inside a module will be grouped under that module. Tests can be added to a module using the QUnit.test method. Modules help organize, select, and filter tests to run. See § Organizing your tests.
Modules can be nested inside other modules. In the output, tests are generally prefixed by the names of all parent modules. E.g. "Grandparent > Parent > Child > my test". See § Nested module scope.
The QUnit.module.only()
, QUnit.module.skip()
, and QUnit.module.todo()
methods are aliases for QUnit.module()
that apply the behaviour of QUnit.test.only()
, QUnit.test.skip()
or QUnit.test.todo()
to all a module's tests at once.
You can use hooks to prepare fixtures, or run other setup and teardown logic. Hooks can run around individual tests, or around a whole module.
before
: Run a callback before the first test.beforeEach
: Run a callback before each test.afterEach
: Run a callback after each test.after
: Run a callback after the last test.
You can add hooks via the hooks
parameter of a scoped module, or in the module options
object, or globally for all tests via QUnit.hooks.
Hooks that are added to a module, will also apply to tests in any nested modules.
Hooks that run before a test, are ordered from outer-most to inner-most, in the order that they are added. This means that a test will first run any global beforeEach hooks, then the hooks of parent modules, and finally the hooks added to the immediate module the test is a part of. Hooks that run after a test, are ordered from inner-most to outer-most, in the reverse order. In other words, before
and beforeEach
callbacks form a queue, while afterEach
and after
form a stack.
A hook callback may be an async function, and may return a Promise or any other then-able. QUnit will automatically wait for your hook's asynchronous work to finish before continuing to execute the tests.
Each hook has access to the same assert
object, and test context via this
, as the QUnit.test that the hook is running for. Example: § Using the test context.
parameter | description |
---|---|
assert (object) |
An Assert object. |
It is discouraged to dynamically create a new [QUnit.test](./test.md) from within a hook. In order to satisfy the requirement for the `after` hook to only run once and to be the last hook in a module, QUnit may associate dynamically defined tests with the parent module instead, or as global test. It is recommended to define any dynamic tests via [`QUnit.begin()`](../callbacks/QUnit.begin.md).
You can use the options object to add hooks.
name | description |
---|---|
before (function) |
Runs before the first test. |
beforeEach (function) |
Runs before each test. |
afterEach (function) |
Runs after each test. |
after (function) |
Runs after the last test. |
Properties on the module options object are copied over to the test context object at the start of each test. Such properties can also be changed from the hook callbacks. See § Using the test context.
Example: § Declaring module options.
Modules can be nested to group tests under a common label within a parent module.
The module scope is given a hooks
object which can be used to procedurally add hooks.
parameter | description |
---|---|
hooks (object) |
An object for adding hooks. |
Example: § Nested module scope.
| QUnit 2.4 | The QUnit.module.only()
, QUnit.module.skip()
, and QUnit.module.todo()
aliases were introduced.
| QUnit 2.0 | The before
and after
options were introduced.
| QUnit 1.20 | The nested
scope feature was introduced.
| QUnit 1.16 | The beforeEach
and afterEach
options were introduced.
The setup
and teardown
options were deprecated in QUnit 1.16 and removed in QUnit 2.0.
If QUnit.module
is called without a nested
callback argument, all subsequently defined tests will be grouped into that module until another module is defined.
QUnit.module('Group A');
QUnit.test('basic test example 1', function (assert) {
assert.true(true, 'this is fine');
});
QUnit.test('basic test example 2', function (assert) {
assert.true(true, 'this is also fine');
});
QUnit.module('Group B');
QUnit.test('basic test example 3', function (assert) {
assert.true(true, 'this is fine');
});
QUnit.test('basic test example 4', function (assert) {
assert.true(true, 'this is also fine');
});
Using modern syntax:
const { test } = QUnit;
QUnit.module('Group A');
test('basic test example', assert => {
assert.true(true, 'this is fine');
});
test('basic test example 2', assert => {
assert.true(true, 'this is also fine');
});
QUnit.module('Group B');
test('basic test example 3', assert => {
assert.true(true, 'this is fine');
});
test('basic test example 4', assert => {
assert.true(true, 'this is also fine');
});
QUnit.module('module A', {
before: function () {
// prepare something once for all tests
},
beforeEach: function () {
// prepare something before each test
},
afterEach: function () {
// clean up after each test
},
after: function () {
// clean up once after all tests are done
}
});
const { test } = QUnit;
QUnit.module('Group A', hooks => {
test('basic test example', assert => {
assert.true(true, 'this is fine');
});
test('basic test example 2', assert => {
assert.true(true, 'this is also fine');
});
});
QUnit.module('Group B', hooks => {
test('basic test example 3', assert => {
assert.true(true, 'this is fine');
});
test('basic test example 4', assert => {
assert.true(true, 'this is also fine');
});
});
Use before
/beforeEach
hooks are queued for nested modules. after
/afterEach
hooks are stacked on nested modules.
const { test } = QUnit;
QUnit.module('My Group', hooks => {
// It is valid to call the same hook methods more than once.
hooks.beforeEach(assert => {
assert.ok(true, 'beforeEach called');
});
hooks.afterEach(assert => {
assert.ok(true, 'afterEach called');
});
test('with hooks', assert => {
// 1 x beforeEach
// 1 x afterEach
assert.expect(2);
});
QUnit.module('Nested Group', hooks => {
// This will run after the parent module's beforeEach hook
hooks.beforeEach(assert => {
assert.ok(true, 'nested beforeEach called');
});
// This will run before the parent module's afterEach
hooks.afterEach(assert => {
assert.ok(true, 'nested afterEach called');
});
test('with nested hooks', assert => {
// 2 x beforeEach (parent, current)
// 2 x afterEach (current, parent)
assert.expect(4);
});
});
});
The test context object is exposed to hook callbacks.
QUnit.module('Machine Maker', {
beforeEach: function () {
this.maker = new Maker();
this.parts = ['wheels', 'motor', 'chassis'];
}
});
QUnit.test('makes a robot', function (assert) {
this.parts.push('arduino');
assert.equal(this.maker.build(this.parts), 'robot');
assert.deepEqual(this.maker.log, ['robot']);
});
QUnit.test('makes a car', function (assert) {
assert.equal(this.maker.build(this.parts), 'car');
this.maker.duplicate();
assert.deepEqual(this.maker.log, ['car', 'car']);
});
The test context is also available when using the nested scope. Beware that use of the this
binding is not available
in arrow functions.
const { test } = QUnit;
QUnit.module('Machine Maker', hooks => {
hooks.beforeEach(function () {
this.maker = new Maker();
this.parts = ['wheels', 'motor', 'chassis'];
});
test('makes a robot', function (assert) {
this.parts.push('arduino');
assert.equal(this.maker.build(this.parts), 'robot');
assert.deepEqual(this.maker.log, ['robot']);
});
test('makes a car', function (assert) {
assert.equal(this.maker.build(this.parts), 'car');
this.maker.duplicate();
assert.deepEqual(this.maker.log, ['car', 'car']);
});
});
It might be more convenient to use JavaScript's own lexical scope instead:
const { test } = QUnit;
QUnit.module('Machine Maker', hooks => {
let maker;
let parts;
hooks.beforeEach(() => {
maker = new Maker();
parts = ['wheels', 'motor', 'chassis'];
});
test('makes a robot', assert => {
parts.push('arduino');
assert.equal(maker.build(parts), 'robot');
assert.deepEqual(maker.log, ['robot']);
});
test('makes a car', assert => {
assert.equal(maker.build(parts), 'car');
maker.duplicate();
assert.deepEqual(maker.log, ['car', 'car']);
});
});
An example of handling an asynchronous then
able Promise result in hooks. This example uses an ES6 Promise interface that is fulfilled after connecting to or disconnecting from database.
QUnit.module('Database connection', {
before: function () {
return new Promise(function (resolve, reject) {
DB.connect(function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
},
after: function () {
return new Promise(function (resolve, reject) {
DB.disconnect(function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
});
Use QUnit.module.only()
to treat an entire module's tests as if they used QUnit.test.only
instead of QUnit.test
.
QUnit.module('Robot', hooks => {
// ...
});
// Only execute this module when developing the feature,
// skipping tests from other modules.
QUnit.module.only('Android', hooks => {
let android;
hooks.beforeEach(() => {
android = new Android();
});
QUnit.test('Say hello', assert => {
assert.strictEqual(android.hello(), 'Hello, my name is AN-2178!');
});
QUnit.test('Basic conversation', assert => {
android.loadConversationData({
Hi: 'Hello',
"What's your name?": 'My name is AN-2178.',
'Nice to meet you!': 'Nice to meet you too!',
'...': '...'
});
assert.strictEqual(
android.answer("What's your name?"),
'My name is AN-2178.'
);
});
// ...
});
Use QUnit.module.skip()
to treat an entire module's tests as if they used QUnit.test.skip
instead of QUnit.test
.
QUnit.module('Robot', hooks => {
// ...
});
// Skip this module's tests.
// For example if the android tests are failing due to unsolved problems.
QUnit.module.skip('Android', hooks => {
let android;
hooks.beforeEach(() => {
android = new Android();
});
QUnit.test('Say hello', assert => {
assert.strictEqual(android.hello(), 'Hello, my name is AN-2178!');
});
QUnit.test('Basic conversation', assert => {
// ...
assert.strictEqual(
android.answer('Nice to meet you!'),
'Nice to meet you too!'
);
});
// ...
});
Use QUnit.module.todo()
to denote a feature that is still under development, and is known to not yet be passing all its tests. This treats an entire module's tests as if they used QUnit.test.todo
instead of QUnit.test
.
QUnit.module.todo('Robot', hooks => {
let robot;
hooks.beforeEach(() => {
robot = new Robot();
});
QUnit.test('Say', assert => {
// Currently, it returns undefined
assert.strictEqual(robot.say(), "I'm Robot FN-2187");
});
QUnit.test('Move arm', assert => {
// Move the arm to point (75, 80). Currently, each throws a NotImplementedError
robot.moveArmTo(75, 80);
assert.deepEqual(robot.getPosition(), { x: 75, y: 80 });
});
// ...
});