[go: nahoru, domu]

Skip to content
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

tests: better error handling when test modules fail to load #15421

Merged
merged 3 commits into from
Aug 30, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 59 additions & 32 deletions core/test/scripts/run-mocha-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,19 +222,14 @@ function getTestFiles() {
}

/**
* @param {{numberFailures: number, numberMochaInvocations: number}} params
* @param {{numberFailures: number}} params
*/
function exit({numberFailures, numberMochaInvocations}) {
function exit({numberFailures}) {
if (!numberFailures) {
console.log('Tests passed');
process.exit(0);
}

if (numberMochaInvocations === 1) {
console.log('Tests failed');
process.exit(1);
}

// If running many instances of mocha, failed results can get lost in the output.
// So keep track of failures and re-print them at the very end.
// See mocha-setup.js afterAll.
Expand Down Expand Up @@ -277,33 +272,65 @@ function exit({numberFailures, numberMochaInvocations}) {
* @param {number} invocationNumber
*/
async function runMocha(tests, mochaArgs, invocationNumber) {
process.env.LH_FAILED_TESTS_FILE = `${failedTestsDir}/output-${invocationNumber}.json`;
const failedTestsFile = `${failedTestsDir}/output-${invocationNumber}.json`;
const notRunnableTestsFile = `${failedTestsDir}/output-${invocationNumber}-not-runnable.json`;
process.env.LH_FAILED_TESTS_FILE = failedTestsFile;

const rootHooksPath = mochaArgs.require || '../test-env/mocha-setup.js';
const {rootHooks} = await import(rootHooksPath);

try {
const mocha = new Mocha({
rootHooks,
timeout: 20_000,
bail: mochaArgs.bail,
grep: mochaArgs.grep,
forbidOnly: mochaArgs.forbidOnly,
// TODO: not working
// parallel: tests.length > 1 && mochaArgs.parallel,
parallel: false,
retries: mochaArgs.retries,
});

// @ts-expect-error - not in types.
mocha.lazyLoadFiles(true);
for (const test of tests) mocha.addFile(test);
await mocha.loadFilesAsync();
return await new Promise(resolve => mocha.run(resolve));
} catch (err) {
console.error(err);
return 1;
const mocha = new Mocha({
rootHooks,
timeout: 20_000,
bail: mochaArgs.bail,
grep: mochaArgs.grep,
forbidOnly: mochaArgs.forbidOnly,
// TODO: not working
// parallel: parsableTests.length > 1 && mochaArgs.parallel,
parallel: false,
retries: mochaArgs.retries,
});

// Load a single test module at a time, so we know which ones fail to even import.
const notRunnableTests = [];
const parsableTests = [];
for (const test of tests) {
try {
mocha.files = [test];
await mocha.loadFilesAsync();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't just await import because mocha does some non trivial logic for importing + setting up mocha globals.

parsableTests.push(test);
} catch (e) {
notRunnableTests.push({
file: path.relative(LH_ROOT, test),
title: '',
error: `Failed to parse module: ${e}`,
});
}
}
mocha.files = [];

let failingTestCount = 0;
if (parsableTests.length) {
try {
failingTestCount = await new Promise(resolve => mocha.run(resolve));
} catch (err) {
// Something awful happened, and maybe no tests ran at all.
const errorMessage = `Mocha failed to run: ${err}`;
notRunnableTests.push(...parsableTests.map((test, i) => {
return {
file: path.relative(LH_ROOT, test),
title: '',
error: i === 0 ? errorMessage : '(see above failure)',
};
}));
}
}

if (notRunnableTests.length) {
fs.writeFileSync(notRunnableTestsFile, JSON.stringify(notRunnableTests, null, 2));
}

return failingTestCount + notRunnableTests.length;
}

async function main() {
Expand Down Expand Up @@ -348,7 +375,7 @@ async function main() {
if (testsToRunTogether.length) {
numberFailures += await runMocha(testsToRunTogether, mochaArgs, numberMochaInvocations);
numberMochaInvocations += 1;
if (numberFailures && argv.bail) exit({numberFailures, numberMochaInvocations});
if (numberFailures && argv.bail) exit({numberFailures});
}

for (const test of testsToRunIsolated) {
Expand All @@ -371,13 +398,13 @@ async function main() {
}

numberMochaInvocations += 1;
if (numberFailures && argv.bail) exit({numberFailures, numberMochaInvocations});
if (numberFailures && argv.bail) exit({numberFailures});
}
} finally {
mochaGlobalTeardown();
}

exit({numberFailures, numberMochaInvocations});
exit({numberFailures});
}

await main();
Loading