Is there a way in mochajs to list all tests collected by test runner without executing them?
E.g. if there are specs that look like:
describe('First', function() {
it('should test something', function() {
...
})
});
describe('Second', function() {
it('should test something else', function() {
...
})
});
then I want to get console output similar to an output produced by test reporters, but without executing actual tests, like this:
First
should test something
Second
should test something else
UPD:
Currently I'm extracting all describe
s and it
s with regex, but looking for a cleaner solution.
You can skip tests by placing an x in front of the describe or it block, or placing a . skip after it.
Retrying Mocha testsMocha provides a this. retries() function that allows you specify the number of times a failed test can be retried. For each retry, Mocha reruns the beforeEach() and afterEach() Hooks but not the before() and after() Hooks.
A pending test in many test framework is test that the runner decided to not run. Sometime it's because the test is flagged to be skipped. Sometime because the test is a just a placeholder for a TODO. For Mocha, the documentation says that a pending test is a test without any callback.
Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub. Use Mocha at Work?
By adding an argument (usually named done) to it () to a test callback, Mocha will know that it should wait for this function to be called to complete the test. This callback accepts both an Error instance (or subclass thereof) or a falsy value; anything else is invalid usage and throws an error (usually causing a failed test).
By appending .skip (), you may tell Mocha to simply ignore test case (s). Anything skipped will be marked as pending, and reported as such. Here's an example of skipping an individual test: describe ('Array', function () { describe ('#indexOf ()', function () { it.skip ('should return -1 unless present',...
When a test file is loaded, Mocha executes all of its suites and finds– but does not execute –any hooks and tests therein. Top-level hooks, tests and suites are all made members of an “invisible” root suite; there is only one root suite for the entire process
The mocha-list-tests package is useful, but only works for BDD style describe()
and it()
, and it breaks if you .skip()
any tests because it mocks it()
.
One way to do this yourself if you need to overcome either of those things, or get other information on the tests, is to exploit Mocha's root before()
hook. This will be executed after Mocha has loaded all files but before it executes any tests, so all the information you need exists at that point.
This way, it is pretty easy to patch in a --list-only
command line option to switch the behaviour of your test run without having to add or change anything else.
The key is that this
in the before()
hook is Mocha's Context
, and the .test
of that refers to the hook itself. So this.test.parent
refers to the root suite. From there, you can walk down the tree of .suites
arrays, and .tests
arrays of each suite.
Having collected whatever you want, you have to then output that and exit the process to stop Mocha from continuing.
Given root.js:
#!/bin/env mocha
before(function() {
if(process.argv.includes('--list-only')) {
inspectSuite(this.test.parent, 0);
process.exit(0);
}
// else let Mocha carry on as normal...
});
function inspectSuite(suite, depth) {
console.log(indent(`Suite ${suite.title || '(root)'}`, depth));
suite.suites.forEach(suite => inspectSuite(suite, depth +1));
suite.tests.forEach(test => inspectTest(test, depth +1));
}
function inspectTest(test, depth) {
console.log(indent(`Test ${test.title}`, depth));
}
function indent(text, by) {
return ' '.repeat(by) + text;
}
And test.js:
#!/bin/env mocha
describe('foo', function() {
describe('bar', function() {
it('should do something', function() {
// ...
});
});
describe('baz', function() {
it.skip('should do something else', function() {
// ...
});
it('should do another thing', function() {
// ...
});
});
});
Then running mocha
as normal would give you the test results you expect:
foo
bar
✓ should do something
baz
- should do something else
✓ should do another thing
2 passing (8ms)
1 pending
But running mocha --list-only
would give you (without running any tests):
Suite (root)
Suite foo
Suite bar
Test should do something
Suite baz
Test should do something else
Test should do another thing
root.js
#!/bin/env mocha
before(function() {
let suites = 0;
let tests = 0;
let pending = 0;
let root = mapSuite(this.test.parent);
process.stdout.write(JSON.stringify({suites, tests, pending, root}, null, ' '));
process.exit(0);
function mapSuite(suite) {
suites += +!suite.root;
return {
title: suite.root ? '(root)' : suite.title,
suites: suite.suites.map(mapSuite),
tests: suite.tests.map(mapTest)
};
}
function mapTest(test) {
++tests;
pending += +test.pending;
return {
title: test.title,
pending: test.pending
};
}
});
With the same test script as before would give you:
{
"suites": 3,
"tests": 3,
"pending": 1,
"root": {
"title": "(root)",
"suites": [
{
"title": "foo",
"suites": [
{
"title": "bar",
"suites": [],
"tests": [
{
"title": "should do something",
"pending": false
}
]
},
{
"title": "baz",
"suites": [],
"tests": [
{
"title": "should do something else",
"pending": true
},
{
"title": "should do another thing",
"pending": false
}
]
}
],
"tests": []
}
],
"tests": []
}
}
Wrap all your describe blocks in a describe block and skip it.
describe.skip('Outline', function() {
describe('First', function() {
it('should test something', function() {
...
})
});
describe('Second', function() {
it('should test something else', function() {
...
})
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With