-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Describe block with async function behaving weirdly #2975
Comments
Async functions are syntactic sugar for returned promise chains, and Mocha's For cases where the names of the tests or how many tests there are can only be determined asynchronously, there is the If you don't need the data to define the tests but only to run them, you can use async If you can come up with a real use case where |
@ScottFreeCode , I have similar problem noted above. Describe('some statement', function(){ before(function(done){ some async function;
}) }) It block does not wait till before is complete. ' it' races around . Now remove the async function , (dynamically forming tests). Before works as expected. |
Hi @caphale, I get errors if I copy-paste this code into a new test file and try to run it, so I can't exactly debug what's happening. I don't even know whether by "Now remove the async function..." you mean the asynchronous code in the I can take some guesses, but these are just guesses:
P.S. If you wrap your code in: |
I want to fetch test data and use it to partially apply a validation function. doing it in beforeEach would defeat the purpose, since I wouldn't have the data outside the scope of the test suite('muh data', async () => {
const DATA = await fetch('data.json').then(jsonify);
// checks that only path has changed
// original -> path -> obj -> assertion
const validatePropChanges = curry((original, path, obj) {/* yadda yadda */});
const validate = validatePropChanges(DATA);
test('incrementFoo only increments foo', () => {
const cloned = clone(DATA);
incrementFoo(cloned);
cloned.foo.should.equal(DATA.foo + 1);
validate('foo', DATA)
}); |
I'd use this approach const validatePropChanges = curry((original, path, obj) {/* yadda yadda */});
suite('muh data', function() {
let validate;
let DATA;
before(async function() {
const DATA = await fetch('data.json').then(jsonify);
validate = validatePropChanges(DATA);
})
test('incrementFoo only increments foo', () => {
const cloned = clone(DATA);
incrementFoo(cloned);
cloned.foo.should.equal(DATA.foo + 1);
validate('foo', DATA)
}); |
I am a bot that watches issues for inactivity. |
It's not stale because of #3243 |
In TypeScript projects, the lack of ability to use async describe functions leads to the following: I want to write: describe('express middleware', async () => {
const {logger, mw} = await elb.middleware({level: 'info'});
// ...
} What I need to write: describe('express middleware', () => {
type ThenArg<T> = T extends Promise<infer U> ? U : T;
type ElbThenType = ThenArg<ReturnType<typeof elb.middleware>>;
let logger: ElbThenType['logger'];
let mw: ElbThenType['mw'];
before(async () => {
({logger, mw} = await elb.middleware({level: 'info'}));
}); It would be quite handy if |
Is there any plan to fix this? I need async |
Why not spin up MongoDB in root-level |
@plroebuck describe("Suite", async () => {
const mongoURI = await spinOffMongoAndReturnConnectionString();
const configuration = {
...readConfigFromEnv(),
mongoURI
};
const expressApp = createTestApp(configuration);
it('should do magic', async () => {
const res = await chai.request(expressApp).put('/some/url').send({ ... });
res.body.should.be.equal(true);
});
}) ps: I would gladly move mongo setup to global hook that runs once before everything happens. |
Maybe... let dbconn;
before(async () => {
dbconn = await spinOffMongoAndReturnConnectionString();
});
describe("Suite", () => {
let expressApp;
before(() => {
const configuration = {
...readConfigFromEnvSync(),
dbconn
};
expressApp = createTestAppSync(configuration);
});
it('should do magic', async () => {
const res = await chai.request(expressApp).put('/some/url').send({ ... });
res.body.should.be.equal(true);
});
after(() => {
expressApp = null;
});
})
after(() => {
dbconn = null;
}); |
@plroebuck Thanks. Surely that works except that Flow doesn't know how mocha works so it will likely force me to check if ps: on the side note, |
LOL... it('should do magic', async () => {
// $FlowMocha
const res = await chai.request(expressApp).put('/some/url').send({ ... });
res.body.should.be.equal(true);
}); ".flowconfig"
|
I struggled with this same problem for a while (certain tests mysteriously not running) until I found this issue posted. I had just assumed |
@alex-at-cascade, well at least you'll get a warning from the upcoming release... |
Just to add to the discussion that our company got caught out by the non-async nature of describe when a developer changed from describe.only('aqs.utils', async () => {
await import('./equals');
await import('./gas');
await import('./notEquals');
await import('./startsWith');
await import('./wordSearch');
}); We went back to the original and now works as expected, but I think we would prefer to use describe.only('aqs.utils', () => {
require('./equals');
require('./gas');
require('./notEquals');
require('./startsWith');
require('./wordSearch');
}); |
Is there any plan to fix this in the long term? |
Yeah this behavior is a pain, resulted in a lot of weird race conditions for me. What worked for me: if you need |
After reading this post I posted the following feature suggestion/analysis - "Feature async-describe -- Analysis of required design & usage changes" #4641 |
the describe('my lib', () => {
let whatever: string;
before(async () => {
whatever = await referenceImplementation();
});
descripbe(`implementation`, () => {
it(`should match: [${whatever}]`, () => {
myImplementation().should.equal(whatever);
});
});
}); Regardless, why is there such resistance to Technically one can do anything without |
I believe they want to keep the "build up the structure of where the tests are" as synchronous as possible. |
Mocha runs in different cycles, we have a description of those in our docs. In the "parsing" cycle all Then in the next cycle the If you need to run an aynchronous job before |
I hadn't see top-level await was available on mocha. That should work for my purposes however TS -> ESM support is still new. Still don't see how it makes sense to prevent this. |
@juergba just to add a use case for the reason you may with a async describe block. I am generating some dynamic tests, and without being able to dynamically describe |
I thought `it` blocks were async but `describe` blocks were not... Or is
that Jest?
…On Tue, Jan 18, 2022 at 3:22 AM ahilton-godaddy ***@***.***> wrote:
@juergba <https://github.com/juergba> just to add a use case for the
reason you may with a async describe block.
I am generating some dynamic tests, and without being able to dynamically
describe it blocks, it makes dynamic test generation a difficult thing to
do, and something people do attempt :D
—
Reply to this email directly, view it on GitHub
<#2975 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFMAAWGATYKOL5U263IHQLUWVEOZANCNFSM4DYWOEOA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you commented.Message ID:
***@***.***>
|
@jcollum You are correct. I'm wondering why |
wanted to add to this by mentioning that ESM is now the official standard for Node.js and require is no longer available within ESM scope. I do love splitting up my tests this way and I hope Mocha can support asynchronously importing test files in the future. IMHO this issue should be opened back up. [edit]: it also looks like people were looking at Jest to support the same thing for similar reasons => jestjs/jest#2235 |
That mocha reports "all good" after "0 Passed" (because it thought no tests had been defined) is one of the problems here. It's easy to blindly switch to @Mikkal24 Have you see the (new in v9.1) |
That --fail-zero would only help if ALL your tests were in that one describe.. |
I am aware that that switching to imports results in the tests not executing. I assume this is because the import function returns a promise and I just wanted to tack on to what @WORMSS said in 2018 because while I can only hope Mocha devs will support this syntax in the future. describe("some group", async ()=>{
await import("myModule.js");
await import("myOtherModule.js");
}) this would help a lot with maintaining large code bases. (TBF I've only got like 100 test files, I would be desperate for this if I had 4200 lol) |
@juergba it looks like more and more people are falling into this trap. It's a bit dangerous when the testing tool just stops running part of the tests without any errors or warnings. And the lack of support for asynchronous For me, the main reason for using async |
Asynchronous describe would be really useful to me in my situation, I have a recursive function that loops through an object and dynamically imports a file (dynamic imports are async) corresponding to the index, creates an Edit: The following solution worked okay for me, still not great tho: export default async function asyncDescribe(desc: string, run: Function) {
const its: Record<string, Function | undefined> = {}
return run((testName: string, func?: Function) => {
its[testName] = func
}).then(() => {
describe(desc, () => {
for (const [testName, runFunction] of Object.entries(its)) {
it(testName, runFunction)
}
})
})
} and you use top-level await on the function |
@boneskull can we reopen this as it's still not fixed? |
juergba commented on Jan 3, 2022:
This is helpful information which I could not find in the documentation. There's no reference to 'parsing' anywhere and the asynchronous discussion does not mention the fact that |
mocha describe() does not accept an async function. Any async prep should be done in a before() function, which does support async. One helpful ref: mochajs/mocha#2975 (comment)
* docs: Add warning about async callback for describe I couldn't find any reference to `describe` not supporting an async function. It seems like a natural idea given `it` and `before` do. I spent considerable time trying to figure out why an async test was failing before I discovered the reason deep in an issue discussion (#2975 (comment)), so hope that this helps others design their test suites! * Update docs/index.md Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com> * Update docs/index.md Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com> --------- Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
Mocha 3.5
Node 8.4
Running this test should give
But its giving
0 passing
Also modifying the above code to
Runs the test but doesn't print the name of describe i.e Test Suite 1
✓should print email
Removing the async from describe and putting it in it works fine
Also .only and .skip do not work when async function is included in the describe block
The text was updated successfully, but these errors were encountered: