Test JavaScript code in a real browser with QUnit.
Getting started
QUnit releases are standalone and require no runtime dependencies for use in the browser. To get started, all you need is an HTML file that loads two files: qunit.js
and qunit.css
.
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>QUnit</title>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.22.0.css">
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://code.jquery.com/qunit/qunit-2.22.0.js"></script>
<!-- <script src="your_app.test.js"></script> -->
</body>
</html>
This is typically saved as /test.html
or /test/index.html
in your project.
The above example loads QUnit from the jQuery CDN. For improved experience during local or offline development, it is recommended to install or download QUnit within your project. Some integrations, like Web Test Runner and Karma, can auto-create the HTML from a list of JS files or glob pattern.
Let’s add the following script, which tests an “add” function that adds two numbers together:
<script>
function add(a, b) {
return a + b;
}
QUnit.module('add', function() {
QUnit.test('two numbers', function(assert) {
assert.equal(add(1, 2), 3);
});
});
</script>
Open your HTML file in a browser to find a detailed report. Live example (open in a new tab):
Congrats! You just executed your first QUnit test!
Fixture
Don’t worry about DOM changes from one test affecting other tests, because QUnit will automatically reset the markup after each test. As long as you append or insert your elements inside the fixture, you will never have to manually clean up after your tests.
This helps keep your tests them atomic!
Find examples and learn more at QUnit.config.fixture
.
Efficient development
As your project grows, you may reach a point where the complete test suite takes more than a second or two to run. QUnit provides several automatic and optional ways to maintain a good feedback cycle.
QUnit’s reorder feature automatically remembers failing tests, and prioritizes those when you reload the page, running them before all other tests. Together with “Hide passed tests” in the toolbar, this let’s you stay focussed by running and showing only what matters most.
When building out a larger feature, you can use the module selector to re-run only the tests (and nested modules) under one or more selected module names.
Browser support
QUnit currently supports the following browsers:
- Internet Explorer: 9+
- Edge: 15+ (both legacy MSEdge and Chromium-based)
- Firefox: 45+
- Safari: 9+
- Opera: 36+
- Chrome: 58+
- Android: 4.3+
- iOS: 7+ (Mobile Safari)
For older browsers, such as Internet Explorer 6-8, Opera 12+, or Safari 5+, please use QUnit 1.x, which you can download from the release archives.
Integrations
Linting
The eslint-plugin-qunit package has a variety of rules available for enforcing best testing practices as well as detecting broken tests.
Browser automation
The following integrations can be used to automate the running of browser tests with QUnit:
- grunt-contrib-qunit for Grunt task runner (test Headless Chrome).
- testem (test any local browser, including headless)
- wdio-qunit-service (test any local, headless, or cloud browser; via WDIO selenium driver)
- Web Test Runner with web-test-runner-qunit (test any local, headless, or cloud browser)
- Karma with karma-qunit (test any local browser or cloud).
- node-qunit-puppeteer (test Headless Chrome).
- StealJS with steal-qunit via Testee (test any local browser or cloud).
- testcafe (test any local browser or cloud).
Example projects:
- Krinkle/example-node-and-browser-qunit-ci: Run QUnit tests locally and in CI, on Headless Firefox and Chrome (using Karma), and with Node.js.
Also demonstrates code coverage, and testing of isomorphic JavaScript projects.
URL parameters
Markup
QUnit requires no HTML markup in order to run tests. The above “Getting started” example is recommended for new projects, but you can customize this as-needed.
To display test results, the only markup necessary is a <div>
with id="qunit"
. Without this, the tests will run with the HTML Reporter disabled.
Browser automations that run tests for you from the command-line, might enable other reporters or event listeners instead. For example, they might use a TAP reporter, or QUnit.on()
to automatically extract results in a machine-readable way, and use it to set the build status of a continuous integration job (CI).
HTML Reporter
The header of the report displays:
- the page title.
- a green bar when all tests passed, or a red bar if one or more tests failed.
- the
navigator.userAgent
string, handy when comparing results captured from different browsers.
Toolbar
Hide passed tests is useful when a lot of tests ran and only a few failed. Ticking the checkbox will show only the tests that failed..
Check for globals detects if a test creates or removes global variable is. QUnit keeps a list of properties found on the window
object. If properties were added or removed, the test fails.
No try-catch instructs QUnit to run your tests without a try-catch block. In this mode, if your test throws an error it will interrupt QUnit, which may ease debugging with browser devtools.
You can extend the toolbar via QUnit.config.urlConfig.
Test results explained
Each result is displayed in a numbered list.
MyApp: example (3) Rerun
After the name of the module and test, in parentheses, is the total number of assertions.
The “Rerun” link at the end will reload the page and quickly run the test again in isolation, skipping all other tests.
Click on the test name to expand the entry, which reveals the message of each assertion.
For failed assertions:
- The parenthetical reports the “failed, passed, and total” number of assertions.
- The expanded view displays the expected and actual asserted value, with a diff to highlight the difference between the two values.
- The source where the failing assertion is performed. The stack trace indicates the test file path and line number.
- The source where the test is defined.
Filter
Enter a search phrase to re-run only tests that match the phrase. It performs a case-insensitive substring match by default, on both the module name and test name. You can use regular expressions, and/or invert the match to exclude tests instead.
Find examples and learn more at QUnit.config.filter.
Module selector
To quickly re-run one or more modules of tests, select them from the module selector and press “Apply”.
You can use the input field to quickly find a module, even if you have many modules. The input field performs fuzzy matching, so don’t worry about getting it exactly right! For example, typing bor game
or abGame
will find awesome board games
. This is similar to how “Quick Open” works in modern text editors.
When selecting a parent module, which contains nested modules, the nested modules and their tests will also be run.
Theme API
The HTML Reporter populates the <div id="qunit">
element with the following structure:
QUnit 1.x, 2.x:
<div id="qunit">
<h1 id="qunit-header">…</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar">…</div>
<h2 id="qunit-userAgent">…</h2>
<p id="qunit-testresult">…</p>
<ol id="qunit-tests"></ol>
</div>
As of QUnit 3.0
<div id="qunit">
<div id="qunit-header">
<h1>…</h1>
<div id="qunit-userAgent">…</div>
</div>
<div id="qunit-toolbar">
<div id="qunit-banner"></div>
<div id="qunit-testrunner-toolbar"></div>
<div id="qunit-testresult"></div>
</div>
<ol id="qunit-tests"></ol>
</div>
You can style these to create your own theme, or add custom styles to the default theme.
Examples: Theme plugins
The following selectors are considered stable and supported:
Selector | Description |
---|---|
#qunit-header #qunit-header a |
Displays the page title, with an anchor link that will reload the page and re-run all tests. |
#qunit-banner #qunit-banner.qunit-pass #qunit-banner.qunit-fail |
Indicates the test run status. It carries no class while tests are in progress. Once completed, the qunit-pass or qunit-fail indicated the completed status as reported by the runEnd event. |
#qunit-testrunner-toolbar |
The toolbar. |
#qunit-userAgent |
QUnit version and user agent string. |
#qunit-modulefilter |
Module selector. |
#qunit-modulefilter-dropdown |
Module selector, dropdown menu. |
#qunit-modulefilter-actions #qunit-modulefilter-actions button |
Module selector, top area of dropdown menu with “Reset” and “Apply” buttons. |
#qunit-modulefilter .clickable #qunit-modulefilter .clickable.checked |
Module selector, options in the dropdown menu. |
#qunit-tests |
List of test items. |
#qunit-tests > li QUnit 3: .qunit-test |
Test item. |
#qunit-tests > li:not(.skipped):not(.pass):not(.fail) QUnit 3: .qunit-test.running |
Currently running test. |
#qunit-tests > li.pass #qunit-tests > li.fail #qunit-tests > li.skipped QUnit 3: .qunit-test.pass .qunit-test.fail .qunit-test.skipped |
Test by one of the three mutually-exclusive outcomes (pass, fail, skipped). |
#qunit-tests > li.todo QUnit 3: .qunit-test.todo |
Test was marked as “todo”. It will also have the pass or fail class. |
.qunit-assert-list |
List of one assertions under a given test. |
HTML API
Test output id="qunit-test-output-TESTID"
You may rely on an element with the following ID existing during test execution. This includes during module hooks, global hooks, and during the test itself and its assertions.
Seeking an element by this ID during an event, or during a different test, may work at your own risk. This is because the HTML Reporter may not have created the element yet, or may have removed it from the DOM (e.g. when hidepassed is enabled).
Demos:
The test ID can be obtained from QUnit.config.current.
QUnit.hooks.afterEach(function () {
var target = '#qunit-test-output-' + QUnit.config.current.testId;
});
QUnit.assert.myplugin = function (actual, expected) {
var target = '#qunit-test-output-' + QUnit.config.current.testId;
};
Toolbar HTML
It is recommended to extend the toolbar declaratively via QUnit.config.urlConfig. Modifying the toolbar elements directly may work at your own risk.