mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-16 22:37:09 +01:00
Add dotnet-trx support (no annotations yet)
This commit is contained in:
parent
6482e393f9
commit
b28f91cc2e
7 changed files with 247 additions and 4 deletions
115
src/parsers/dotnet-trx/dotnet-trx-parser.ts
Normal file
115
src/parsers/dotnet-trx/dotnet-trx-parser.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import {ErrorInfo, Outcome, TestMethod, TrxReport} from './dotnet-trx-types'
|
||||
|
||||
import {Annotation, ParseOptions, TestResult} from '../parser-types'
|
||||
import {parseStringPromise} from 'xml2js'
|
||||
|
||||
import {parseAttribute} from '../../utils/xml-utils'
|
||||
import {Icon} from '../../utils/markdown-utils'
|
||||
|
||||
import {
|
||||
TestExecutionResult,
|
||||
TestRunResult,
|
||||
TestSuiteResult,
|
||||
TestGroupResult,
|
||||
TestCaseResult
|
||||
} from '../../report/test-results'
|
||||
import getReport from '../../report/get-report'
|
||||
|
||||
class TestClass {
|
||||
constructor(readonly name: string) {}
|
||||
readonly tests: Test[] = []
|
||||
}
|
||||
|
||||
class Test {
|
||||
constructor(
|
||||
readonly name: string,
|
||||
readonly outcome: Outcome,
|
||||
readonly duration: number,
|
||||
readonly error?: ErrorInfo
|
||||
) {}
|
||||
|
||||
get result(): TestExecutionResult {
|
||||
switch (this.outcome) {
|
||||
case 'Passed':
|
||||
return 'success'
|
||||
case 'NotExecuted':
|
||||
return 'skipped'
|
||||
case 'Failed':
|
||||
return 'failed'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function parseDotnetTrx(content: string, options: ParseOptions): Promise<TestResult> {
|
||||
const trx = (await parseStringPromise(content, {
|
||||
attrValueProcessors: [parseAttribute]
|
||||
})) as TrxReport
|
||||
|
||||
const testClasses = getTestClasses(trx)
|
||||
const testRun = getTestRunResult(trx, testClasses)
|
||||
const success = testRun.result === 'success'
|
||||
const icon = success ? Icon.success : Icon.fail
|
||||
|
||||
return {
|
||||
success,
|
||||
output: {
|
||||
title: `${options.name.trim()} ${icon}`,
|
||||
summary: getReport(testRun),
|
||||
annotations: options.annotations
|
||||
? getAnnotations(/*testClasses, options.workDir, options.trackedFiles*/)
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTestRunResult(trx: TrxReport, testClasses: TestClass[]): TestRunResult {
|
||||
const times = trx.TestRun.Times[0].$
|
||||
const totalTime = times.finish.getTime() - times.start.getTime()
|
||||
|
||||
const suites = testClasses.map(tc => {
|
||||
const tests = tc.tests.map(t => new TestCaseResult(t.name, t.result, t.duration))
|
||||
const group = new TestGroupResult(null, tests)
|
||||
return new TestSuiteResult(tc.name, [group])
|
||||
})
|
||||
|
||||
return new TestRunResult(suites, totalTime)
|
||||
}
|
||||
|
||||
function getTestClasses(trx: TrxReport): TestClass[] {
|
||||
const unitTests: {[id: string]: TestMethod} = {}
|
||||
for (const td of trx.TestRun.TestDefinitions) {
|
||||
for (const ut of td.UnitTest) {
|
||||
unitTests[ut.$.id] = ut.TestMethod[0]
|
||||
}
|
||||
}
|
||||
|
||||
const unitTestsResults = trx.TestRun.Results.flatMap(r => r.UnitTestResult).flatMap(unitTestResult => ({
|
||||
unitTestResult,
|
||||
testMethod: unitTests[unitTestResult.$.testId]
|
||||
}))
|
||||
|
||||
const testClasses: {[name: string]: TestClass} = {}
|
||||
for (const r of unitTestsResults) {
|
||||
let tc = testClasses[r.testMethod.$.className]
|
||||
if (tc === undefined) {
|
||||
tc = new TestClass(r.testMethod.$.className)
|
||||
testClasses[tc.name] = tc
|
||||
}
|
||||
const output = r.unitTestResult.Output
|
||||
const error = output?.length > 0 && output[0].ErrorInfo?.length > 0 ? output[0].ErrorInfo[0] : undefined
|
||||
const test = new Test(r.testMethod.$.name, r.unitTestResult.$.outcome, r.unitTestResult.$.duration, error)
|
||||
tc.tests.push(test)
|
||||
}
|
||||
|
||||
const result = Object.values(testClasses)
|
||||
result.sort((a, b) => a.name.localeCompare(b.name))
|
||||
for (const tc of result) {
|
||||
tc.tests.sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function getAnnotations(/*testClasses: TestClass[], workDir: string, trackedFiles: string[]*/): Annotation[] {
|
||||
return []
|
||||
}
|
||||
60
src/parsers/dotnet-trx/dotnet-trx-types.ts
Normal file
60
src/parsers/dotnet-trx/dotnet-trx-types.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
export interface TrxReport {
|
||||
TestRun: TestRun
|
||||
}
|
||||
|
||||
export interface TestRun {
|
||||
Times: Times[]
|
||||
Results: Results[]
|
||||
TestDefinitions: TestDefinitions[]
|
||||
}
|
||||
|
||||
export interface Times {
|
||||
$: {
|
||||
creation: Date
|
||||
queuing: Date
|
||||
start: Date
|
||||
finish: Date
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestDefinitions {
|
||||
UnitTest: UnitTest[]
|
||||
}
|
||||
|
||||
export interface UnitTest {
|
||||
$: {
|
||||
id: string
|
||||
}
|
||||
TestMethod: TestMethod[]
|
||||
}
|
||||
|
||||
export interface TestMethod {
|
||||
$: {
|
||||
className: string
|
||||
name: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Results {
|
||||
UnitTestResult: UnitTestResult[]
|
||||
}
|
||||
|
||||
export interface UnitTestResult {
|
||||
$: {
|
||||
testId: string
|
||||
testName: string
|
||||
duration: number
|
||||
outcome: Outcome
|
||||
}
|
||||
Output: Output[]
|
||||
}
|
||||
|
||||
export interface Output {
|
||||
ErrorInfo: ErrorInfo[]
|
||||
}
|
||||
export interface ErrorInfo {
|
||||
Message: string[]
|
||||
StackTrace: string[]
|
||||
}
|
||||
|
||||
export type Outcome = 'Passed' | 'NotExecuted' | 'Failed'
|
||||
Loading…
Add table
Add a link
Reference in a new issue