feat(testrunner): allow filtering by name and show all focused tests (#1354)

This commit is contained in:
Andrey Lushnikov 2020-03-11 18:30:43 -07:00 committed by GitHub
parent b43f33f4d3
commit 1cd00bd068
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 120 additions and 78 deletions

View file

@ -124,9 +124,10 @@ for (const browserConfig of BROWSER_CONFIGS) {
}); });
} }
if (process.env.CI && testRunner.hasFocusedTestsOrSuites()) { const filterArgIndex = process.argv.indexOf('--filter');
console.error('ERROR: "focused" tests/suites are prohibited on bots. Remove any "fit"/"fdescribe" declarations.'); if (filterArgIndex !== -1) {
process.exit(1); const filter = process.argv[filterArgIndex + 1];
testRunner.focusMatchingTests(new RegExp(filter, 'i'));
} }
new Reporter(testRunner, { new Reporter(testRunner, {

View file

@ -47,7 +47,18 @@ class Reporter {
if (allTests.length === runnableTests.length) { if (allTests.length === runnableTests.length) {
console.log(`Running all ${colors.yellow(runnableTests.length)} tests on ${colors.yellow(this._runner.parallel())} worker${this._runner.parallel() > 1 ? 's' : ''}:\n`); console.log(`Running all ${colors.yellow(runnableTests.length)} tests on ${colors.yellow(this._runner.parallel())} worker${this._runner.parallel() > 1 ? 's' : ''}:\n`);
} else { } else {
console.log(`Running ${colors.yellow(runnableTests.length)} focused tests out of total ${colors.yellow(allTests.length)} on ${colors.yellow(this._runner.parallel())} worker${this._runner.parallel() > 1 ? 's' : ''}:\n`); console.log(`Running ${colors.yellow(runnableTests.length)} focused tests out of total ${colors.yellow(allTests.length)} on ${colors.yellow(this._runner.parallel())} worker${this._runner.parallel() > 1 ? 's' : ''}`);
console.log('');
const focusedSuites = this._runner.focusedSuites();
const focusedTests = this._runner.focusedTests();
if (focusedSuites.length) {
console.log('Focused Suites and Tests:');
for (let i = 0; i < focusedSuites.length; ++i)
console.log(` ${i + 1}) ${focusedSuites[i].fullName} (${formatLocation(focusedSuites[i].location)})`);
for (let i = 0; i < focusedTests.length; ++i)
console.log(` ${i + 1 + focusedSuites.length}) ${focusedTests[i].fullName} (${formatLocation(focusedTests[i].location)})`);
console.log('');
}
} }
} }

View file

@ -116,6 +116,7 @@ class Suite {
this.declaredMode = declaredMode; this.declaredMode = declaredMode;
/** @type {!Array<(!Test|!Suite)>} */ /** @type {!Array<(!Test|!Suite)>} */
this.children = []; this.children = [];
this.location = getCallerLocation(__filename);
this.beforeAll = null; this.beforeAll = null;
this.beforeEach = null; this.beforeEach = null;
@ -441,18 +442,19 @@ class TestRunner extends EventEmitter {
timeout = 10 * 1000, // Default timeout is 10 seconds. timeout = 10 * 1000, // Default timeout is 10 seconds.
parallel = 1, parallel = 1,
breakOnFailure = false, breakOnFailure = false,
crashIfTestsAreFocusedOnCI = true,
disableTimeoutWhenInspectorIsEnabled = true, disableTimeoutWhenInspectorIsEnabled = true,
} = options; } = options;
this._crashIfTestsAreFocusedOnCI = crashIfTestsAreFocusedOnCI;
this._sourceMapSupport = new SourceMapSupport(); this._sourceMapSupport = new SourceMapSupport();
this._rootSuite = new Suite(null, '', TestMode.Run); this._rootSuite = new Suite(null, '', TestMode.Run);
this._currentSuite = this._rootSuite; this._currentSuite = this._rootSuite;
this._tests = []; this._tests = [];
this._suites = [];
this._timeout = timeout === 0 ? INFINITE_TIMEOUT : timeout; this._timeout = timeout === 0 ? INFINITE_TIMEOUT : timeout;
this._parallel = parallel; this._parallel = parallel;
this._breakOnFailure = breakOnFailure; this._breakOnFailure = breakOnFailure;
this._hasFocusedTestsOrSuites = false;
if (MAJOR_NODEJS_VERSION >= 8 && disableTimeoutWhenInspectorIsEnabled) { if (MAJOR_NODEJS_VERSION >= 8 && disableTimeoutWhenInspectorIsEnabled) {
if (inspector.url()) { if (inspector.url()) {
console.log('TestRunner detected inspector; overriding certain properties to be debugger-friendly'); console.log('TestRunner detected inspector; overriding certain properties to be debugger-friendly');
@ -508,18 +510,17 @@ class TestRunner extends EventEmitter {
const test = new Test(this._currentSuite, name, callback, mode, timeout); const test = new Test(this._currentSuite, name, callback, mode, timeout);
this._currentSuite.children.push(test); this._currentSuite.children.push(test);
this._tests.push(test); this._tests.push(test);
this._hasFocusedTestsOrSuites = this._hasFocusedTestsOrSuites || mode === TestMode.Focus;
return test; return test;
} }
_addSuite(mode, name, callback, ...args) { _addSuite(mode, name, callback, ...args) {
const oldSuite = this._currentSuite; const oldSuite = this._currentSuite;
const suite = new Suite(this._currentSuite, name, mode); const suite = new Suite(this._currentSuite, name, mode);
this._suites.push(suite);
this._currentSuite.children.push(suite); this._currentSuite.children.push(suite);
this._currentSuite = suite; this._currentSuite = suite;
callback(...args); callback(...args);
this._currentSuite = oldSuite; this._currentSuite = oldSuite;
this._hasFocusedTestsOrSuites = this._hasFocusedTestsOrSuites || mode === TestMode.Focus;
} }
_addHook(hookName, callback) { _addHook(hookName, callback) {
@ -530,15 +531,21 @@ class TestRunner extends EventEmitter {
async run() { async run() {
let session = this._debuggerLogBreakpointLines.size ? await setLogBreakpoints(this._debuggerLogBreakpointLines) : null; let session = this._debuggerLogBreakpointLines.size ? await setLogBreakpoints(this._debuggerLogBreakpointLines) : null;
const runnableTests = this._runnableTests(); const runnableTests = this.runnableTests();
this.emit(TestRunner.Events.Started, runnableTests); this.emit(TestRunner.Events.Started, runnableTests);
const result = {};
if (this._crashIfTestsAreFocusedOnCI && process.env.CI && this.hasFocusedTestsOrSuites()) {
result.result = TestResult.Crashed;
result.exitCode = 2;
result.terminationMessage = '"focused" tests or suites are probitted on CI';
} else {
this._runningPass = new TestPass(this, this._parallel, this._breakOnFailure); this._runningPass = new TestPass(this, this._parallel, this._breakOnFailure);
const termination = await this._runningPass.run(runnableTests).catch(e => { const termination = await this._runningPass.run(runnableTests).catch(e => {
console.error(e); console.error(e);
throw e; throw e;
}); });
this._runningPass = null; this._runningPass = null;
const result = {};
if (termination) { if (termination) {
result.result = termination.result; result.result = termination.result;
result.exitCode = 130; result.exitCode = 130;
@ -553,6 +560,7 @@ class TestRunner extends EventEmitter {
result.exitCode = 0; result.exitCode = 0;
} }
} }
}
this.emit(TestRunner.Events.Finished, result); this.emit(TestRunner.Events.Finished, result);
if (session) if (session)
session.disconnect(); session.disconnect();
@ -569,8 +577,8 @@ class TestRunner extends EventEmitter {
return this._timeout; return this._timeout;
} }
_runnableTests() { runnableTests() {
if (!this._hasFocusedTestsOrSuites) if (!this.hasFocusedTestsOrSuites())
return this._tests; return this._tests;
const tests = []; const tests = [];
@ -601,8 +609,23 @@ class TestRunner extends EventEmitter {
return tests.map(t => t.test); return tests.map(t => t.test);
} }
focusedSuites() {
return this._suites.filter(suite => suite.declaredMode === 'focus');
}
focusedTests() {
return this._tests.filter(test => test.declaredMode === 'focus');
}
hasFocusedTestsOrSuites() { hasFocusedTestsOrSuites() {
return this._hasFocusedTestsOrSuites; return !!this.focusedTests().length || !!this.focusedSuites().length;
}
focusMatchingTests(fullNameRegex) {
for (const test of this._tests) {
if (fullNameRegex.test(test.fullName))
test.declaredMode = 'focus';
}
} }
tests() { tests() {

View file

@ -1,5 +1,12 @@
const {TestRunner} = require('..'); const {TestRunner} = require('..');
function newTestRunner(options) {
return new TestRunner({
crashIfTestsAreFocusedOnCI: false,
...options,
});
}
module.exports.addTests = function({testRunner, expect}) { module.exports.addTests = function({testRunner, expect}) {
const {describe, fdescribe, xdescribe} = testRunner; const {describe, fdescribe, xdescribe} = testRunner;
const {it, xit, fit} = testRunner; const {it, xit, fit} = testRunner;