Use team city messages for mocha test output

This commit is contained in:
Ilya Goncharov
2019-10-10 15:21:45 +03:00
parent 07e4b1f3de
commit a4c761aa33
2 changed files with 38 additions and 97 deletions
@@ -1,5 +1,7 @@
import {CliArgsParser, getDefaultCliDescription} from "./src/CliArgsParser";
import {getFilteringAdapter} from "./src/Adapter";
import {runWithTeamCityReporter} from "./src/KotlinTestTeamCityReporter";
import {TeamCityMessagesFlow} from "./src/TeamCityMessagesFlow";
const kotlin_test = require('kotlin-test');
@@ -29,5 +31,10 @@ const defaultMochaArgs = [
const processArgs = process.argv.slice(2, -1 * defaultMochaArgs.length);
const untypedArgs = parser.parse(processArgs);
// TODO(ilgonmic): Try to detect adapter
const initialAdapter = new kotlin_test.kotlin.test.adapters.JasmineLikeAdapter();
kotlin_test.setAdapter(getFilteringAdapter(initialAdapter, untypedArgs));
const realConsoleLog = console.log;
const teamCity = new TeamCityMessagesFlow(null, (payload) => realConsoleLog(payload));
const teamCityAdapter = runWithTeamCityReporter(initialAdapter, teamCity);
kotlin_test.setAdapter(getFilteringAdapter(teamCityAdapter, untypedArgs));
@@ -1,6 +1,5 @@
import {KotlinTestRunner} from "./KotlinTestRunner";
import {TeamCityMessageData, TeamCityMessagesFlow} from "./TeamCityMessagesFlow";
import {Timer} from "./Timer";
import {format} from "util";
const kotlin_test = require('kotlin-test');
@@ -23,113 +22,48 @@ function withName(name: string, data?: TeamCityMessageData): TeamCityMessageData
export function runWithTeamCityReporter(
runner: KotlinTestRunner,
ignoredTestSuites: IgnoredTestSuitesReporting,
teamCity: TeamCityMessagesFlow,
timer: Timer<any> | null
teamCity: TeamCityMessagesFlow
): KotlinTestRunner {
let inIgnoredSuite = false;
let currentAssertionResult: { expected: any, actual: any } | null = null;
kotlin_test.kotlin.test.setAssertHook_4duqou$(function (assertionResult: { expected: any, actual: any }) {
currentAssertionResult = assertionResult;
});
return {
suite: function (name: string, isIgnored: boolean, fn: () => void) {
if (isIgnored) {
if (ignoredTestSuites == IgnoredTestSuitesReporting.skip) return;
else if (ignoredTestSuites == IgnoredTestSuitesReporting.reportAsIgnoredTest) {
teamCity.sendMessage('testIgnored', withName(name, {"suite": true}));
return
}
}
teamCity.sendMessage('testSuiteStarted', withName(name));
// noinspection UnnecessaryLocalVariableJS
const alreadyInIgnoredSuite = inIgnoredSuite;
if (!alreadyInIgnoredSuite && isIgnored) {
inIgnoredSuite = true;
}
try {
if (isIgnored && ignoredTestSuites == IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored) {
fn();
} else {
runner.suite(name, isIgnored, fn)
}
} finally {
if (isIgnored && !alreadyInIgnoredSuite) {
inIgnoredSuite = false;
}
const data: TeamCityMessageData = withName(name);
// extension only for Gradle
if (isIgnored) data["ignored"] = true;
teamCity.sendMessage('testSuiteFinished', data);
}
runner.suite(name, isIgnored, fn)
},
test: function (name: string, isIgnored: boolean, fn: () => void) {
if (inIgnoredSuite || isIgnored) {
teamCity.sendMessage('testIgnored', withName(name));
} else {
const startTime = timer ? timer.start() : null;
teamCity.sendMessage('testStarted', withName(name));
let revertLogMethods: CallableFunction[] = [];
let revertLogMethods: CallableFunction[] = [];
runner.test(name, isIgnored, () => {
const log = (type: string) => function (message?: any, ...optionalParams: any[]) {
teamCity.sendMessage(
"testStdOut",
withName(
name,
{
"out": `[${type}] ${format(message, ...optionalParams)}\n`
}
)
)
};
const logMethods = ['log', 'info', 'warn', 'error', 'debug'];
const globalConsole = console as unknown as {
[method: string]: (message?: any, ...optionalParams: any[]) => void
};
revertLogMethods = logMethods
.map(method => {
const realMethod = globalConsole[method];
globalConsole[method] = log(method);
return () => globalConsole[method] = realMethod
});
try {
runner.test(name, isIgnored, () => {
const log = (type: string) => function (message?: any, ...optionalParams: any[]) {
teamCity.sendMessage(
"testStdOut",
withName(
name,
{
"out": `[${type}] ${format(message, ...optionalParams)}\n`
}
)
)
};
const logMethods = ['log', 'info', 'warn', 'error', 'debug'];
const globalConsole = console as unknown as {
[method: string]: (message?: any, ...optionalParams: any[]) => void
};
revertLogMethods = logMethods
.map(method => {
const realMethod = globalConsole[method];
globalConsole[method] = log(method);
return () => globalConsole[method] = realMethod
});
fn();
});
fn();
} catch (e) {
const data: TeamCityMessageData = withName(name, {
"message": e.message,
"details": e.stack
});
if (currentAssertionResult) {
data["type"] = 'comparisonFailure';
data["expected"] = currentAssertionResult.expected;
data["actual"] = currentAssertionResult.actual;
}
teamCity.sendMessage('testFailed', data);
throw e;
} finally {
revertLogMethods.forEach(revert => revert());
currentAssertionResult = null;
const data: TeamCityMessageData = withName(name);
if (startTime) {
data["duration"] = timer!!.end(startTime); // ns to ms
}
teamCity.sendMessage('testFinished', data);
}
}
});
}
}
}