Github ActionにJob Summaryという機能があり、これを使うとActionの結果をmarkdownに対して出力できる。
所属しているチームではPlaywrightをテストに使用しているのだが、毎回Actionの実行でエラーがおきたときにStepを開いて見に行く必要があり、まあまあ面倒。第一に見ずらい。
そこで、playwrightが提供しているReporterでJob Summary用の実装を用意すると、こんな感じでテスト結果をいい感じに表示できる。
エラーがあるときは各リトライの結果を表示させるようしている。
import * as fs from 'fs'; import {FullConfig, TestError} from '@playwright/test'; import {FullResult, Reporter, Suite, TestCase, TestResult} from '@playwright/test/reporter'; interface Error { title: string; error: TestError; } export default class GithubSummaryReporter implements Reporter { outputFile?: fs.WriteStream; errors: Error[]; onBegin(config: FullConfig, suite: Suite) { const summaryFile = process.env.GITHUB_STEP_SUMMARY if (summaryFile) { this.outputFile = fs.createWriteStream(summaryFile, {flags: 'a'}); } this.errors = []; this.writeOut("## Summary\n") this.writeOut("Case|Status|Duration") this.writeOut("----|------|--------") } onEnd(result: FullResult) { if (this.errors.length > 0) { let errorDetails = "\n## Errors\n" this.errors.forEach(({title, error}, attempt) => { errorDetails += `\n#### ${title} (#${attempt} attempt)`; errorDetails += "\n```diff\n"; errorDetails += error.message.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "") errorDetails += "\n```\n"; }) this.writeOut(errorDetails) } if (this.outputFile) { this.outputFile.end(); this.outputFile.close(); } } onTestEnd(test: TestCase, result: TestResult) { const title = test.titlePath().filter(v => v !== '').join(' > '); const status = result.status === 'passed' ? ':white_check_mark:' : ':x:'; if (result.status !== 'passed') { result.errors.forEach(error => { this.errors.push({title, error}) }) } this.writeOut(`${title} (#${result.retry})|${status}|${result.duration}ms`) } private writeOut(value: string) { if (this.outputFile) { this.outputFile.write(value + "\n"); } else { console.log(value) } } }
細かい話だが、エラーメッセージのsyntaxをdiffにすると差分がいい感じで表示できる。
あとはreplaceでANSIエスケープシーケンスを取り除くところもポイントで、playwrightはレポータに渡してくるエラーメッセージの文字列にカラーコードがつけっぱなしなのでレポータ側で外してやらないといけない。