test: dump workers state after the test runner is terminated (#2991)

This will help us to debug the flakes on the CI.
This commit is contained in:
Andrey Lushnikov 2018-07-30 18:57:48 -07:00 committed by GitHub
parent 0c825de1f8
commit 862ad96bde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 18 deletions

View File

@ -27,6 +27,7 @@ class Reporter {
runner.on('finished', this._onFinished.bind(this)); runner.on('finished', this._onFinished.bind(this));
runner.on('teststarted', this._onTestStarted.bind(this)); runner.on('teststarted', this._onTestStarted.bind(this));
runner.on('testfinished', this._onTestFinished.bind(this)); runner.on('testfinished', this._onTestFinished.bind(this));
this._workersState = new Map();
} }
_onStarted() { _onStarted() {
@ -43,6 +44,26 @@ class Reporter {
console.log('Stack:'); console.log('Stack:');
console.log(error.stack.split('\n').map(line => ' ' + line).join('\n')); console.log(error.stack.split('\n').map(line => ' ' + line).join('\n'));
} }
console.log('WORKERS STATE');
const workerIds = Array.from(this._workersState.keys());
workerIds.sort();
for (const workerId of workerIds) {
const {isRunning, test} = this._workersState.get(workerId);
let description = '';
if (isRunning)
description = `${YELLOW_COLOR}RUNNING${RESET_COLOR}`;
else if (test.result === 'ok')
description = `${GREEN_COLOR}OK${RESET_COLOR}`;
else if (test.result === 'skipped')
description = `${YELLOW_COLOR}SKIPPED${RESET_COLOR}`;
else if (test.result === 'failed')
description = `${RED_COLOR}FAILED${RESET_COLOR}`;
else if (test.result === 'timedout')
description = `${RED_COLOR}TIMEDOUT${RESET_COLOR}`;
else
description = `${RED_COLOR}<UNKNOWN>${RESET_COLOR}`;
console.log(` ${workerId}: [${description}] ${test.fullName} (${formatTestLocation(test)})`);
}
process.exit(2); process.exit(2);
} }
@ -61,7 +82,7 @@ class Reporter {
console.log('\nFailures:'); console.log('\nFailures:');
for (let i = 0; i < failedTests.length; ++i) { for (let i = 0; i < failedTests.length; ++i) {
const test = failedTests[i]; const test = failedTests[i];
console.log(`${i + 1}) ${test.fullName} (${formatLocation(test)})`); console.log(`${i + 1}) ${test.fullName} (${formatTestLocation(test)})`);
if (test.result === 'timedout') { if (test.result === 'timedout') {
console.log(' Message:'); console.log(' Message:');
console.log(` ${YELLOW_COLOR}Timeout Exceeded ${this._runner.timeout()}ms${RESET_COLOR}`); console.log(` ${YELLOW_COLOR}Timeout Exceeded ${this._runner.timeout()}ms${RESET_COLOR}`);
@ -98,7 +119,7 @@ class Reporter {
for (let i = 0; i < skippedTests.length; ++i) { for (let i = 0; i < skippedTests.length; ++i) {
const test = skippedTests[i]; const test = skippedTests[i];
console.log(`${i + 1}) ${test.fullName}`); console.log(`${i + 1}) ${test.fullName}`);
console.log(` ${YELLOW_COLOR}Temporary disabled with xit${RESET_COLOR} ${formatLocation(test)}\n`); console.log(` ${YELLOW_COLOR}Temporary disabled with xit${RESET_COLOR} ${formatTestLocation(test)}\n`);
} }
} }
@ -107,19 +128,14 @@ class Reporter {
const milliseconds = Date.now() - this._timestamp; const milliseconds = Date.now() - this._timestamp;
const seconds = milliseconds / 1000; const seconds = milliseconds / 1000;
console.log(`Finished in ${YELLOW_COLOR}${seconds}${RESET_COLOR} seconds`); console.log(`Finished in ${YELLOW_COLOR}${seconds}${RESET_COLOR} seconds`);
function formatLocation(test) {
const location = test.location;
if (!location)
return '';
return `${location.fileName}:${location.lineNumber}:${location.columnNumber}`;
}
} }
_onTestStarted() { _onTestStarted(test, workerId) {
this._workersState.set(workerId, {test, isRunning: true});
} }
_onTestFinished(test) { _onTestFinished(test, workerId) {
this._workersState.set(workerId, {test, isRunning: false});
if (test.result === 'ok') if (test.result === 'ok')
process.stdout.write(`${GREEN_COLOR}.${RESET_COLOR}`); process.stdout.write(`${GREEN_COLOR}.${RESET_COLOR}`);
else if (test.result === 'skipped') else if (test.result === 'skipped')
@ -131,4 +147,11 @@ class Reporter {
} }
} }
function formatTestLocation(test) {
const location = test.location;
if (!location)
return '';
return `${location.fileName}:${location.lineNumber}:${location.columnNumber}`;
}
module.exports = Reporter; module.exports = Reporter;

View File

@ -208,10 +208,10 @@ class TestPass {
async _runTest(workerId, test, state) { async _runTest(workerId, test, state) {
if (this._termination) if (this._termination)
return; return;
this._runner._willStartTest(test); this._runner._willStartTest(test, workerId);
if (test.declaredMode === TestMode.Skip) { if (test.declaredMode === TestMode.Skip) {
test.result = TestResult.Skipped; test.result = TestResult.Skipped;
this._runner._didFinishTest(test); this._runner._didFinishTest(test, workerId);
return; return;
} }
this._runningUserCallbacks.set(workerId, test._userCallback); this._runningUserCallbacks.set(workerId, test._userCallback);
@ -226,7 +226,7 @@ class TestPass {
test.result = TestResult.TimedOut; test.result = TestResult.TimedOut;
else else
test.result = TestResult.Failed; test.result = TestResult.Failed;
this._runner._didFinishTest(test); this._runner._didFinishTest(test, workerId);
} }
async _runHook(workerId, suite, hookName, ...args) { async _runHook(workerId, suite, hookName, ...args) {
@ -380,12 +380,12 @@ class TestRunner extends EventEmitter {
return this._parallel; return this._parallel;
} }
_willStartTest(test) { _willStartTest(test, workerId) {
this.emit('teststarted', test); this.emit(TestRunner.Events.TestStarted, test, workerId);
} }
_didFinishTest(test) { _didFinishTest(test, workerId) {
this.emit('testfinished', test); this.emit(TestRunner.Events.TestFinished, test, workerId);
} }
} }