Handle test reports with no test cases

This commit is contained in:
Michal Dorner 2021-03-07 10:34:20 +01:00
parent a1cbedbccb
commit a9749e3840
No known key found for this signature in database
GPG key ID: 9EEE04B48DA36786
13 changed files with 114 additions and 18 deletions

View file

@ -7,6 +7,22 @@ import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('dart-json tests', () => { describe('dart-json tests', () => {
it('produces empty test run result when there are no test cases', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'dart-json.json')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DartJsonParser(opts, 'dart')
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
})
it('matches report snapshot', async () => { it('matches report snapshot', async () => {
const opts: ParseOptions = { const opts: ParseOptions = {
parseErrors: true, parseErrors: true,

View file

@ -7,6 +7,22 @@ import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('dotnet-trx tests', () => { describe('dotnet-trx tests', () => {
it('produces empty test run result when there are no test cases', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'dotnet-trx.trx')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetTrxParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
})
it('matches report snapshot', async () => { it('matches report snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx') const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const outputPath = path.join(__dirname, '__outputs__', 'dotnet-trx.md') const outputPath = path.join(__dirname, '__outputs__', 'dotnet-trx.md')

View file

@ -0,0 +1,9 @@
{"protocolVersion":"0.1.1","runnerVersion":"1.15.4","pid":21320,"type":"start","time":0}
{"suite":{"id":0,"platform":"vm","path":"test\\main_test.dart"},"type":"suite","time":0}
{"test":{"id":1,"name":"loading test\\main_test.dart","suiteID":0,"groupIDs":[],"metadata":{"skip":false,"skipReason":null},"line":null,"column":null,"url":null},"type":"testStart","time":1}
{"suite":{"id":2,"platform":"vm","path":"test\\second_test.dart"},"type":"suite","time":11}
{"test":{"id":3,"name":"loading test\\second_test.dart","suiteID":2,"groupIDs":[],"metadata":{"skip":false,"skipReason":null},"line":null,"column":null,"url":null},"type":"testStart","time":11}
{"count":2,"type":"allSuites","time":11}
{"testID":1,"result":"success","skipped":false,"hidden":true,"type":"testDone","time":4018}
{"testID":3,"result":"success","skipped":false,"hidden":true,"type":"testDone","time":4025}
{"success":true,"type":"done","time":4029}

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<TestRun id="80e4c095-f726-4ab2-9441-416daa162672" name="..." runUser="..." xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Times creation="2021-02-26T10:36:33.7131022+02:00" queuing="2021-02-26T10:36:33.7131029+02:00" start="2021-02-26T10:36:33.3278956+02:00" finish="2021-02-26T10:36:33.7139830+02:00" />
<TestSettings name="default" id="863a1d8b-ee3b-45f9-86ee-1869bc4e889f">
<Deployment runDeploymentRoot="..." />
</TestSettings>
<TestLists>
<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
</TestLists>
<ResultSummary outcome="Completed">
<Counters total="0" executed="0" passed="0" failed="0" error="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />
<RunInfos>
<RunInfo computerName="..." outcome="Warning" timestamp="2021-02-26T10:36:33.6676104+02:00">
<Text>No test is available in (...). Make sure that test discoverer &amp; executors are registered and platform &amp; framework version settings are appropriate and try again.</Text>
</RunInfo>
</RunInfos>
</ResultSummary>
</TestRun>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="jest tests" tests="0" failures="0" errors="0" time="11.299">
</testsuites>

View file

@ -7,6 +7,22 @@ import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('jest-junit tests', () => { describe('jest-junit tests', () => {
it('produces empty test run result when there are no test cases', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'jest-junit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JestJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
})
it('report from ./reports/jest test results matches snapshot', async () => { it('report from ./reports/jest test results matches snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'jest-junit.xml') const fixturePath = path.join(__dirname, 'fixtures', 'jest-junit.xml')
const outputPath = path.join(__dirname, '__outputs__', 'jest-junit.md') const outputPath = path.join(__dirname, '__outputs__', 'jest-junit.md')

21
dist/index.js generated vendored
View file

@ -669,6 +669,9 @@ class DotnetTrxParser {
} }
getTestClasses(trx) { getTestClasses(trx) {
var _a; var _a;
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined) {
return [];
}
const unitTests = {}; const unitTests = {};
for (const td of trx.TestRun.TestDefinitions) { for (const td of trx.TestRun.TestDefinitions) {
for (const ut of td.UnitTest) { for (const ut of td.UnitTest) {
@ -789,12 +792,14 @@ class JestJunitParser {
} }
} }
getTestRunResult(path, junit) { getTestRunResult(path, junit) {
const suites = junit.testsuites.testsuite.map(ts => { const suites = junit.testsuites.testsuite === undefined
const name = ts.$.name.trim(); ? []
const time = parseFloat(ts.$.time) * 1000; : junit.testsuites.testsuite.map(ts => {
const sr = new test_results_1.TestSuiteResult(name, this.getGroups(ts), time); const name = ts.$.name.trim();
return sr; const time = parseFloat(ts.$.time) * 1000;
}); const sr = new test_results_1.TestSuiteResult(name, this.getGroups(ts), time);
return sr;
});
const time = parseFloat(junit.testsuites.$.time) * 1000; const time = parseFloat(junit.testsuites.$.time) * 1000;
return new test_results_1.TestRunResult(path, suites, time); return new test_results_1.TestRunResult(path, suites, time);
} }
@ -1114,7 +1119,9 @@ function getSuitesReport(tr, runIndex, options) {
const icon = getResultIcon(tr.result); const icon = getResultIcon(tr.result);
sections.push(`## ${nameLink} ${icon}`); sections.push(`## ${nameLink} ${icon}`);
const time = markdown_utils_1.formatTime(tr.time); const time = markdown_utils_1.formatTime(tr.time);
const headingLine2 = `**${tr.tests}** tests were completed in **${time}** with **${tr.passed}** passed, **${tr.failed}** failed and **${tr.skipped}** skipped.`; const headingLine2 = tr.tests > 0
? `**${tr.tests}** tests were completed in **${time}** with **${tr.passed}** passed, **${tr.failed}** failed and **${tr.skipped}** skipped.`
: 'No tests found';
sections.push(headingLine2); sections.push(headingLine2);
const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites; const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites;
if (suites.length > 0) { if (suites.length > 0) {

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View file

@ -61,6 +61,10 @@ export class DotnetTrxParser implements TestParser {
} }
private getTestClasses(trx: TrxReport): TestClass[] { private getTestClasses(trx: TrxReport): TestClass[] {
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined) {
return []
}
const unitTests: {[id: string]: TestMethod} = {} const unitTests: {[id: string]: TestMethod} = {}
for (const td of trx.TestRun.TestDefinitions) { for (const td of trx.TestRun.TestDefinitions) {
for (const ut of td.UnitTest) { for (const ut of td.UnitTest) {

View file

@ -4,8 +4,8 @@ export interface TrxReport {
export interface TestRun { export interface TestRun {
Times: Times[] Times: Times[]
Results: Results[] Results?: Results[]
TestDefinitions: TestDefinitions[] TestDefinitions?: TestDefinitions[]
} }
export interface Times { export interface Times {

View file

@ -32,12 +32,15 @@ export class JestJunitParser implements TestParser {
} }
private getTestRunResult(path: string, junit: JunitReport): TestRunResult { private getTestRunResult(path: string, junit: JunitReport): TestRunResult {
const suites = junit.testsuites.testsuite.map(ts => { const suites =
const name = ts.$.name.trim() junit.testsuites.testsuite === undefined
const time = parseFloat(ts.$.time) * 1000 ? []
const sr = new TestSuiteResult(name, this.getGroups(ts), time) : junit.testsuites.testsuite.map(ts => {
return sr const name = ts.$.name.trim()
}) const time = parseFloat(ts.$.time) * 1000
const sr = new TestSuiteResult(name, this.getGroups(ts), time)
return sr
})
const time = parseFloat(junit.testsuites.$.time) * 1000 const time = parseFloat(junit.testsuites.$.time) * 1000
return new TestRunResult(path, suites, time) return new TestRunResult(path, suites, time)

View file

@ -10,7 +10,7 @@ export interface TestSuites {
errors: string // unhandled exception during test execution errors: string // unhandled exception during test execution
time: string time: string
} }
testsuite: TestSuite[] testsuite?: TestSuite[]
} }
export interface TestSuite { export interface TestSuite {

View file

@ -148,7 +148,10 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
sections.push(`## ${nameLink} ${icon}`) sections.push(`## ${nameLink} ${icon}`)
const time = formatTime(tr.time) const time = formatTime(tr.time)
const headingLine2 = `**${tr.tests}** tests were completed in **${time}** with **${tr.passed}** passed, **${tr.failed}** failed and **${tr.skipped}** skipped.` const headingLine2 =
tr.tests > 0
? `**${tr.tests}** tests were completed in **${time}** with **${tr.passed}** passed, **${tr.failed}** failed and **${tr.skipped}** skipped.`
: 'No tests found'
sections.push(headingLine2) sections.push(headingLine2)
const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites