-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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: sequester mocks to -test.mocks.js
files
#14216
Conversation
-test.mocks.js
files-test.mocks.js
files
@@ -299,6 +300,11 @@ async function runMocha(tests, mochaArgs, invocationNumber) { | |||
const rootHooksPath = mochaArgs.require || '../test-env/mocha-setup.js'; | |||
const {rootHooks} = await import(rootHooksPath); | |||
|
|||
let mocksFilePath; | |||
if (tests.length === 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaning on the definitions of "test isolation" above to indirectly control when these mocks
files can be called. When isolation stuff is dropped (I'm working on it now), the runner can be rewritten slightly to instead run files by themselves if they have a mocks
file defined. It wouldn't be a big change to do that in this PR but, I didn't think it was necessary, preferring a more incremental change.
lighthouse-cli/test/cli/bin-test.js
Outdated
}); | ||
/** @type {import('./bin-test.mocks.js').TestContext} */ | ||
// @ts-expect-error | ||
const testContext = global.lighthouseTestContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a roundabout way of doing import {testContext} from './bin-test.mocks.js'
as the first import of the file. Could we do that instead?
Eslint could be updated to enforce this import order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because the import cache is refreshed after every call to td.replaceEsm, hence this whole setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I don't think order of static import evaluation is even specified in ESM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^that's old knowledge. now, it's "source defined order" except for when there is async code in the root module scope, which all of these setup files have.
https://stackoverflow.com/questions/35551366/what-is-the-defined-execution-order-of-es6-imports
This is blocking #14202 and removal of "isolation" from the test runner. |
@@ -171,6 +171,8 @@ const rawArgv = y | |||
const argv = | |||
/** @type {Awaited<typeof rawArgv> & CamelCasify<Awaited<typeof rawArgv>>} */ (rawArgv); | |||
|
|||
process.env.SNAPSHOT_UPDATE = argv.update ? '1' : ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're already doing this in main
right?
What is the blocking part? I thought this was a reorganization for clarity of mocking/import order? |
For windows: #14202 (comment) The errors seen in CI here are similar to what this PR tries to avoid. It could be the issue is elsewhere–I figured I'd wait for this to land and remove an extra source of issues before debugging further. Debugging potential issues being Windows....or quibble....or mocks.... was getting too much so I wanted to just solve one first. For isolation: With this PR we can remove the manual listing of what test files to isolate, and instead either 1) isolate the files implicitly if they have an associated mocks file or 2) go further, and figure out how to run the mocks files just before a test module is loaded within a single Mocha node-api invocation. |
I confirmed that this PR + #14202 fixes windows CI. https://github.com/GoogleChrome/lighthouse/actions/runs/3316847458 |
Is it possible to unblock #14202, without this PR? TBH I would prefer avoiding this solution if we can. It's pretty messy and I'm becoming less concerned about "thinking deeply about the module graph". We could use dynamic imports with toplevel await to avoid the messy |
Please send a draft PR converting |
We are going with the approach in #14468 - see my comment there: #14468 (review) |
The purpose of this refactor is to avoid needing to think deeply about the module graph when mocking modules in a test. Since static imports are run first in ESM, there is no way to (within the same module) mock modules in a way that lets you access those mocked modules through the initial static imports (that's why the dynamic import mess exists right now). Instead, with this PR we define all the
td.replaceEsm
calls in a separate file, which our custom Mocha runner will import before loading the test file. If the test needs access to anything thismocks.js
file sets up, it will be available viaglobal.lighthouseTestContext
.Initially I explored a Mocha-centric solution:
Where the canonical test file name is the "wrapper", and hacks at Mocha's lifecycle via
suite.beforeAll
to setup test suites dynamically just in time. This would have allowed for the Mocha runner to be given multiple such tests (instead of the one-at-a-time method required currently) becausesuite.beforeAll
runs just before Mocha runs the tests for that file. Do the setup in a normal root-scopebeforeAll
or inside adescribe
wouldn't work because tests added dynamically at that point are ignored by Mocha. Some drawbacks here:it.only
and--grep
cease to work for these files