The A-Frame codebase aims for as much unit test coverage as possible. Tests give us confidence that changes work and that they do not unexpectedly regress other parts of the code.
Pull requests changing code behavior will usually be asked to accompany unit tests. Bug fixes will also usually be asked to provide unit tests to prevent future regressions.
Unit tests use:
- karma - The test runner. We configured
npm run test
to run karma on the command line. - Mocha (in TDD mode) - The test framework. Provides things such as test methods, setup/teardown hooks, the reporter.
- chai - An assertion library. In unit tests, we write
code, and assert that certain values are what we think they should be
(e.g.,
assert.equal(value, 5)
). - sinon - A library for stubbing, spying, and mocking. This lets us do things such as assert that functions were or were not called, to stub out and isolate code that we don't want to be executed, or create mock objects. Most tests will not need Sinon.
Run npm run test
to run the entire test suite. This starts a watcher. Every
change to the codebase will automatically trigger the tests. This is useful in
that we don't have to re-run a command every time we want to run the tests.
If we wish to only run a single test suite or a single test case, we can add
either set the TEST_FILE
environment variable pattern. This will match for
files containing the pattern.
TEST_FILE=geometry npm run test
Or add .only
to the suite or test we wish to run. For example:
// To run just this suite, change:
suite('lorum ipsum', function () { // ... });
// to...
suite.only('lorum ipsum', function () { // ... });
// To run just this test, change:
test('lorem ipsum', function () { // ... });
// to...
test.only('lorem ipsum', function () { // ... });
To run only on a specific browser:
npm run test:chrome
TEST_FILE=scene npm run test:firefox
The most useful thing to do is read the existing tests and mimic their structure and style.
Tests are structured with each module, component, or custom element getting their own test suite. Methods or features are inner suites within their respective module, component, or custom element. And then test cases go within those inner suites:
suite('module/component/custom element', function () {
/**
* `setup` hook is run before every test.
*/
setup(function (done) {
done(); // If asynchrony is involved, use `done` to tell when finished.
});
suite('method/feature', function () [
/**
* A synchronous test case. No need to specify `done`.
*/
test('does this', function () {
assert.equal(1, 1);
});
/**
* An asynchronous test case.
*/
test('does that', function (done) {
process.nextTick(function () {
assert.notEqual(1, 2);
done(); // Use `done` to tell when finished in asynchronous test.
});
});
});
});
- Install the Codecov Chrome Extension or Firefox Add-on to view code coverage information on GitHub's UI.
helpers.js:entityFactory
is common called insetup
hooks to setup an entity within a scene that is attached to the body.- When testing with an
<a-entity>
, we often to have wait until it fires the 'loaded' event. - karma may sometimes misreport test failures to other unit tests. Run one test suite or case at a time to isolate the test failure.
- Use
process.nextTick
after doing DOM manipulations. However, we will not need to do this afterEntity.setAttribute
as we have made that synchronous.