Persist test summary on disk

This commit is contained in:
Ray Xu 2022-04-23 05:48:48 +00:00 committed by Zach Renner
parent c9b3d0e2bd
commit 83b7f42d2d
19 changed files with 1284 additions and 3655 deletions

View file

@ -1,5 +1,6 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import * as fs from 'fs'
import {GitHub} from '@actions/github/lib/utils'
import {ArtifactProvider} from './input-providers/artifact-provider'
@ -7,7 +8,6 @@ import {LocalFileProvider} from './input-providers/local-file-provider'
import {FileContent} from './input-providers/input-provider'
import {ParseOptions, TestParser} from './test-parser'
import {TestRunResult} from './test-results'
import {getAnnotations} from './report/get-annotations'
import {getReport} from './report/get-report'
import {DartJsonParser} from './parsers/dart-json/dart-json-parser'
@ -18,7 +18,6 @@ import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser'
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
import {getCheckRunContext} from './utils/github-utils'
import {Icon} from './utils/markdown-utils'
async function main(): Promise<void> {
try {
@ -154,45 +153,50 @@ class TestReporter {
results.push(tr)
}
core.info(`Creating check run ${name}`)
const createResp = await this.octokit.rest.checks.create({
head_sha: this.context.sha,
name,
status: 'in_progress',
output: {
title: name,
summary: ''
},
...github.context.repo
})
// core.info(`Creating check run ${name}`)
// const createResp = await this.octokit.checks.create({
// head_sha: this.context.sha,
// name,
// status: 'in_progress',
// output: {
// title: name,
// summary: ''
// },
// ...github.context.repo
// })
core.info('Creating report summary')
const {listSuites, listTests, onlySummary} = this
const baseUrl = createResp.data.html_url as string
const baseUrl = ''
const summary = getReport(results, {listSuites, listTests, baseUrl, onlySummary})
core.info('Summary content:')
core.info(summary)
await fs.promises.writeFile(this.path.replace('*.trx', 'test-summary.md'), summary)
core.info('File content:')
core.info(fs.readFileSync(this.path.replace('*.trx', 'test-summary.md'), 'utf8'))
core.info('Creating annotations')
const annotations = getAnnotations(results, this.maxAnnotations)
// core.info('Creating annotations')
// const annotations = getAnnotations(results, this.maxAnnotations)
const isFailed = results.some(tr => tr.result === 'failed')
const conclusion = isFailed ? 'failure' : 'success'
const icon = isFailed ? Icon.fail : Icon.success
// const isFailed = results.some(tr => tr.result === 'failed')
// const conclusion = isFailed ? 'failure' : 'success'
// const icon = isFailed ? Icon.fail : Icon.success
core.info(`Updating check run conclusion (${conclusion}) and output`)
const resp = await this.octokit.rest.checks.update({
check_run_id: createResp.data.id,
conclusion,
status: 'completed',
output: {
title: `${name} ${icon}`,
summary,
annotations
},
...github.context.repo
})
core.info(`Check run create response: ${resp.status}`)
core.info(`Check run URL: ${resp.data.url}`)
core.info(`Check run HTML: ${resp.data.html_url}`)
// core.info(`Updating check run conclusion (${conclusion}) and output`)
// const resp = await this.octokit.checks.update({
// check_run_id: createResp.data.id,
// conclusion,
// status: 'completed',
// output: {
// title: `${name} ${icon}`,
// summary,
// annotations
// },
// ...github.context.repo
// })
// core.info(`Check run create response: ${resp.status}`)
// core.info(`Check run URL: ${resp.data.url}`)
// core.info(`Check run HTML: ${resp.data.html_url}`)
return results
}

View file

@ -16,7 +16,10 @@ import {
} from '../../test-results'
class TestClass {
constructor(readonly name: string) {}
constructor(
readonly name: string,
readonly assemblyName: string
) {}
readonly tests: Test[] = []
}
@ -81,9 +84,12 @@ export class DotnetTrxParser implements TestParser {
const testClasses: {[name: string]: TestClass} = {}
for (const r of unitTestsResults) {
const className = r.test.TestMethod[0].$.className
const codeBase = r.test.TestMethod[0].$.codeBase
const pathSegments = codeBase.replace(/\\/g, '/').split('/')
const assemblyName = pathSegments[pathSegments.length - 1].replace('.dll', '')
let tc = testClasses[className]
if (tc === undefined) {
tc = new TestClass(className)
tc = new TestClass(className, assemblyName)
testClasses[tc.name] = tc
}
const error = this.getErrorInfo(r.result)
@ -117,6 +123,10 @@ export class DotnetTrxParser implements TestParser {
return new TestSuiteResult(testClass.name, [group])
})
if (testClasses.length > 0) {
return new TestRunResult(testClasses[0].assemblyName, suites, totalTime)
}
return new TestRunResult(path, suites, totalTime)
}

View file

@ -30,6 +30,7 @@ export interface UnitTest {
export interface TestMethod {
$: {
codeBase: string
className: string
name: string
}

View file

@ -136,16 +136,16 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
const sections: string[] = []
if (testRuns.length > 1 || options.onlySummary) {
const tableData = testRuns.map((tr, runIndex) => {
const time = formatTime(tr.time)
const name = tr.path
const addr = options.baseUrl + makeRunSlug(runIndex).link
const nameLink = link(name, addr)
const passed = tr.passed > 0 ? `${tr.passed}${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed}${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped}${Icon.skip}` : ''
return [nameLink, passed, failed, skipped, time]
})
const tableData = testRuns
.filter(tr => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
.map(tr => {
const time = formatTime(tr.time)
const name = tr.path
const passed = tr.passed > 0 ? `${tr.passed}${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed}${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped}${Icon.skip}` : ''
return [name, passed, failed, skipped, time]
})
const resultsTable = table(
['Report', 'Passed', 'Failed', 'Skipped', 'Time'],

View file

@ -6,9 +6,9 @@ export enum Align {
}
export const Icon = {
skip: '✖️', // ':heavy_multiplication_x:'
success: '✔️', // ':heavy_check_mark:'
fail: '❌' // ':x:'
skip: ':no_entry_sign:',
success: ':white_check_mark:',
fail: ':x:'
}
export function link(title: string, address: string): string {