Description
What is the problem this feature will solve?
When writing tests, I really like the plan
function in tape.
In summary it lets you specify how many assertions you expect to have, then the test will fail if there are fewer/more than planned.
I'm really loving the new built in testing runtime, but I'm really missing plan
. So I've built a wrapper around assert that implements the plan function in a similar way.
import assertPlan from 'assert-plan';
test('test 1 assertion', async t => {
const assert = assertPlan(1);
assert.strictEqual(1, 1);
await assert.wait();
});
https://github.com/markwylde/assert-plan#example-usage
It's working really well, but there's a problem when the test timesout. I would like to log out the test timed out due to not receiving enough planned assertions.
To get around this I have to provide two timeouts, as below: (it works, but it's not very nice):
For example
Notes:
- You can see there is a top timeout of 2000ms, then the assert will timeout at 1500ms.
- When the
assertPlan
times out, it throws and error that is outputted to the user. - this test will hang because it's expecting 2 asserions
- it only receives 1 assertion, therefore throws after 1500
test('test 2 assertions will timeout', { timeout: 2000 }, async t => {
const assert = assertPlan(2, { timeout: 1500 });
assert.strictEqual(1, 1);
await assert.wait();
});
What is the feature you are proposing to solve the problem?
I think there's probably an obvious existing solution, or I'm trying to solve something in a strange way. So I'm really open to criticism on my approach. But some ideas off the top of my head are:
Proposal 1 - expose the timeout on t
test('test 2 assertions will timeout', { timeout: 2000 }, async t => {
const assert = assertPlan(2, { timeout: t.timeout });
});
Proposal 2 - expose an event when a test timesout
test('test 2 assertions will timeout', { timeout: 2000 }, async t => {
const assert = assertPlan(2);
t.onTimeout(assert.cancel);
});
Proposal 3 - test timeout hook
import { onTimeout } from 'node:test';
// triggered anytime a test times out
onTimeout((testFunction) => {
assertPlan.outputPendingAssertPlans();
});
test('test 2 assertions will timeout', { timeout: 2000 }, async t => {
const assert = assertPlan(2);
t.onTimeout(assert.cancel);
});
What alternatives have you considered?
I originally thought if we could add a plan
function to the test runtime, like tape
does:
For example:
import assertPlan from 'assert-plan';
test('test 2 assertions will timeout', { timeout: 2000 }, async t => {
t.plan(2);
assert(1 + 1, 2, '1+1=2');
});
But it breaks the cleanest of the test
module, and how it's not coupled with assert
at all. So I feel the right solution is to wrap/use an alternative assert library.
Maybe we could add a plan
to the assert
module, but you could be running multiple tests in parallel and assert
wouldn't have a way of accumulating counts for just the specific test you are running.
You could make assert
a constructor, but even then the problem of how to timeout the wait when the test timeouts still exists.
Thank you for humoring my idea and sorry if there is some really obvious stuff I'm missing here.