-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add dotnet-trx support (no annotations yet)
- Loading branch information
Michal Dorner
committed
Jan 11, 2021
1 parent
6482e39
commit b28f91c
Showing
7 changed files
with
247 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`dotnet-trx tests matches report snapshot 1`] = ` | ||
Object { | ||
"annotations": Array [], | ||
"summary": "**7** tests were completed in **1.061s** with **3** passed, **1** skipped and **3** failed. | ||
| Result | Suite | Tests | Time | Passed ✔️ | Failed ❌ | Skipped ✖️ | | ||
| :---: | :--- | ---: | ---: | ---: | ---: | ---: | | ||
| ❌ | [DotnetTests.XUnitTests.CalculatorTests](#ts-0-DotnetTests-XUnitTests-CalculatorTests) | 7 | 109.5761ms | 3 | 3 | 1 | | ||
# Test Suites | ||
## <a id=\\"user-content-ts-0-DotnetTests-XUnitTests-CalculatorTests\\" href=\\"#ts-0-DotnetTests-XUnitTests-CalculatorTests\\">DotnetTests.XUnitTests.CalculatorTests</a> ❌ | ||
| Result | Test | Time | | ||
| :---: | :--- | ---: | | ||
| ❌ | Exception_In_TargetTest | 0.4975ms | | ||
| ❌ | Exception_In_Test | 2.2728ms | | ||
| ❌ | Failing_Test | 3.2953ms | | ||
| ✔️ | Passing_Test | 0.1254ms | | ||
| ✔️ | Passing_Test_With_Name | 0.103ms | | ||
| ✖️ | Skipped_Test | 1ms | | ||
| ✔️ | Timeout_Test | 102.2821ms | | ||
", | ||
"title": "Dotnet TRX tests ❌", | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import * as fs from 'fs' | ||
import * as path from 'path' | ||
|
||
import {parseDotnetTrx} from '../src/parsers/dotnet-trx/dotnet-trx-parser' | ||
import {ParseOptions} from '../src/parsers/parser-types' | ||
|
||
const xmlFixture = fs.readFileSync(path.join(__dirname, 'fixtures', 'dotnet-trx.trx'), {encoding: 'utf8'}) | ||
const outputPath = __dirname + '/__outputs__/dotnet-trx.md' | ||
|
||
describe('dotnet-trx tests', () => { | ||
it('matches report snapshot', async () => { | ||
const opts: ParseOptions = { | ||
name: 'Dotnet TRX tests', | ||
annotations: true, | ||
trackedFiles: ['DotnetTests.Unit/Calculator.cs', 'DotnetTests.XUnitTests/CalculatorTests.cs'], | ||
workDir: 'C:/Users/Michal/Workspace/dorny/test-check/reports/dotnet/' | ||
} | ||
|
||
const result = await parseDotnetTrx(xmlFixture, opts) | ||
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) | ||
fs.writeFileSync(outputPath, result?.output?.summary ?? '') | ||
|
||
expect(result.success).toBeFalsy() | ||
expect(result?.output).toMatchSnapshot() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters