fix(tests): fix multiple browsers tests (#1718)

- Use a server only once, not once per browser.
- Avoid require cache for test files.
- Improve testrunner hooks debugging.
This commit is contained in:
Dmitry Gozman 2020-04-08 15:54:17 -07:00 committed by GitHub
parent 6723254266
commit 2d57fff0be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 54 deletions

View file

@ -87,6 +87,9 @@ module.exports.addPlaywrightTests = ({testRunner, products}) => {
delete global.playwright; delete global.playwright;
}); });
testRunner.collector().useEnvironment(serverEnvironment); // Custom global environment.
testRunner.collector().useEnvironment(playwrightEnvironment);
for (const product of products) { for (const product of products) {
const browserTypeEnvironment = new Environment('BrowserType'); const browserTypeEnvironment = new Environment('BrowserType');
browserTypeEnvironment.beforeAll(async state => { browserTypeEnvironment.beforeAll(async state => {
@ -145,8 +148,10 @@ module.exports.addPlaywrightTests = ({testRunner, products}) => {
state.page = null; state.page = null;
}); });
testRunner.collector().useEnvironment(serverEnvironment); // Custom global environment. function loadTest(path) {
testRunner.collector().useEnvironment(playwrightEnvironment); require(path);
delete require.cache[require.resolve(path)];
}
describe(product, () => { describe(product, () => {
// In addition to state, expose these two on global so that describes can access them. // In addition to state, expose these two on global so that describes can access them.
@ -164,66 +169,66 @@ module.exports.addPlaywrightTests = ({testRunner, products}) => {
// Page-level tests that are given a browser, a context and a page. // Page-level tests that are given a browser, a context and a page.
// Each test is launched in a new browser context. // Each test is launched in a new browser context.
require('./accessibility.spec.js'); loadTest('./accessibility.spec.js');
require('./autowaiting.spec.js'); loadTest('./autowaiting.spec.js');
require('./click.spec.js'); loadTest('./click.spec.js');
require('./cookies.spec.js'); loadTest('./cookies.spec.js');
require('./dialog.spec.js'); loadTest('./dialog.spec.js');
require('./download.spec.js'); loadTest('./download.spec.js');
require('./elementhandle.spec.js'); loadTest('./elementhandle.spec.js');
require('./emulation.spec.js'); loadTest('./emulation.spec.js');
require('./evaluation.spec.js'); loadTest('./evaluation.spec.js');
require('./frame.spec.js'); loadTest('./frame.spec.js');
require('./focus.spec.js'); loadTest('./focus.spec.js');
require('./input.spec.js'); loadTest('./input.spec.js');
require('./jshandle.spec.js'); loadTest('./jshandle.spec.js');
require('./keyboard.spec.js'); loadTest('./keyboard.spec.js');
require('./mouse.spec.js'); loadTest('./mouse.spec.js');
require('./navigation.spec.js'); loadTest('./navigation.spec.js');
require('./network.spec.js'); loadTest('./network.spec.js');
require('./page.spec.js'); loadTest('./page.spec.js');
require('./queryselector.spec.js'); loadTest('./queryselector.spec.js');
require('./screenshot.spec.js'); loadTest('./screenshot.spec.js');
require('./waittask.spec.js'); loadTest('./waittask.spec.js');
require('./interception.spec.js'); loadTest('./interception.spec.js');
require('./geolocation.spec.js'); loadTest('./geolocation.spec.js');
require('./workers.spec.js'); loadTest('./workers.spec.js');
require('./capabilities.spec.js'); loadTest('./capabilities.spec.js');
require('./permissions.spec.js'); loadTest('./permissions.spec.js');
describe.skip(product !== 'Chromium')('[Chromium]', () => { describe.skip(product !== 'Chromium')('[Chromium]', () => {
require('./chromium/chromium.spec.js'); loadTest('./chromium/chromium.spec.js');
require('./chromium/coverage.spec.js'); loadTest('./chromium/coverage.spec.js');
require('./chromium/pdf.spec.js'); loadTest('./chromium/pdf.spec.js');
require('./chromium/session.spec.js'); loadTest('./chromium/session.spec.js');
}); });
}); });
// Browser-level tests that are given a browser. // Browser-level tests that are given a browser.
describe('[Driver]', () => { describe('[Driver]', () => {
require('./browser.spec.js'); loadTest('./browser.spec.js');
require('./browsercontext.spec.js'); loadTest('./browsercontext.spec.js');
require('./ignorehttpserrors.spec.js'); loadTest('./ignorehttpserrors.spec.js');
require('./popup.spec.js'); loadTest('./popup.spec.js');
}); });
}); });
// Top-level tests that launch Browser themselves. // Top-level tests that launch Browser themselves.
describe('[Driver]', () => { describe('[Driver]', () => {
require('./defaultbrowsercontext.spec.js'); loadTest('./defaultbrowsercontext.spec.js');
require('./fixtures.spec.js'); loadTest('./fixtures.spec.js');
require('./launcher.spec.js'); loadTest('./launcher.spec.js');
require('./headful.spec.js'); loadTest('./headful.spec.js');
require('./multiclient.spec.js'); loadTest('./multiclient.spec.js');
}); });
describe.skip(product !== 'Chromium')('[Chromium]', () => { describe.skip(product !== 'Chromium')('[Chromium]', () => {
require('./chromium/launcher.spec.js'); loadTest('./chromium/launcher.spec.js');
require('./chromium/oopif.spec.js'); loadTest('./chromium/oopif.spec.js');
require('./chromium/tracing.spec.js'); loadTest('./chromium/tracing.spec.js');
}); });
require('./apicoverage.spec.js'); loadTest('./apicoverage.spec.js');
delete global.browserType; delete global.browserType;
delete global.playwright; delete global.playwright;

View file

@ -264,7 +264,7 @@ class TestWorker {
} }
async _runHook(testRun, hook, fullName, passTestRun = false) { async _runHook(testRun, hook, fullName, passTestRun = false) {
await this._willStartHook(hook, fullName); await this._willStartHook(testRun, hook, fullName);
const timeout = this._testRunner._hookTimeout; const timeout = this._testRunner._hookTimeout;
const { promise, terminate } = runUserCallback(hook.body, timeout, passTestRun ? [this._state, testRun] : [this._state]); const { promise, terminate } = runUserCallback(hook.body, timeout, passTestRun ? [this._state, testRun] : [this._state]);
this._runningHookTerminate = terminate; this._runningHookTerminate = terminate;
@ -289,13 +289,13 @@ class TestWorker {
await this._testRunner._sourceMapSupport.rewriteStackTraceWithSourceMaps(error); await this._testRunner._sourceMapSupport.rewriteStackTraceWithSourceMaps(error);
message = `${hook.location.toDetailedString()} - FAILED while running "${hook.name}" in suite "${fullName}": `; message = `${hook.location.toDetailedString()} - FAILED while running "${hook.name}" in suite "${fullName}": `;
} }
await this._didFailHook(hook, fullName, message, error); await this._didFailHook(testRun, hook, fullName, message, error);
if (testRun) if (testRun)
testRun._error = error; testRun._error = error;
return false; return false;
} }
await this._didCompleteHook(hook, fullName); await this._didCompleteHook(testRun, hook, fullName);
return true; return true;
} }
@ -319,19 +319,19 @@ class TestWorker {
debug('testrunner:test')(`[${this._workerId}] ${testRun._result.toUpperCase()} "${testRun.test().fullName()}" (${testRun.test().location()})`); debug('testrunner:test')(`[${this._workerId}] ${testRun._result.toUpperCase()} "${testRun.test().fullName()}" (${testRun.test().location()})`);
} }
async _willStartHook(hook, fullName) { async _willStartHook(testRun, hook, fullName) {
debug('testrunner:hook')(`[${this._workerId}] "${hook.name}" started for "${fullName}" (${hook.location})`); debug('testrunner:hook')(`[${this._workerId}] "${fullName}.${hook.name}" started for "${testRun ? testRun.test().fullName() : ''}" (${hook.location})`);
} }
async _didFailHook(hook, fullName, message, error) { async _didFailHook(testRun, hook, fullName, message, error) {
debug('testrunner:hook')(`[${this._workerId}] "${hook.name}" FAILED for "${fullName}" (${hook.location})`); debug('testrunner:hook')(`[${this._workerId}] "${fullName}.${hook.name}" FAILED for "${testRun ? testRun.test().fullName() : ''}" (${hook.location})`);
if (message) if (message)
this._testRunner._result.addError(message, error, this); this._testRunner._result.addError(message, error, this);
this._testRunner._result.setResult(TestResult.Crashed, message); this._testRunner._result.setResult(TestResult.Crashed, message);
} }
async _didCompleteHook(hook, fullName) { async _didCompleteHook(testRun, hook, fullName) {
debug('testrunner:hook')(`[${this._workerId}] "${hook.name}" OK for "${fullName}" (${hook.location})`); debug('testrunner:hook')(`[${this._workerId}] "${fullName}.${hook.name}" OK for "${testRun ? testRun.test().fullName() : ''}" (${hook.location})`);
} }
async shutdown() { async shutdown() {