mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-15 13:57:09 +01:00
Merge pull request #571 from Shamus03/feature/golang-json-parser
Add Golang test parser
This commit is contained in:
commit
a8c55a3654
13 changed files with 613 additions and 0 deletions
|
|
@ -16,6 +16,7 @@ This [Github Action](https://github.com/features/actions) displays test results
|
|||
- .NET / [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#examples) ( [xUnit](https://xunit.net/) / [NUnit](https://nunit.org/) / [MSTest](https://github.com/Microsoft/testfx-docs) )
|
||||
- Dart / [test](https://pub.dev/packages/test)
|
||||
- Flutter / [test](https://pub.dev/packages/test)
|
||||
- Go / [go test](https://pkg.go.dev/testing)
|
||||
- Java / [JUnit](https://junit.org/)
|
||||
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
|
||||
- Swift / xUnit
|
||||
|
|
@ -140,6 +141,7 @@ jobs:
|
|||
# dotnet-nunit
|
||||
# dotnet-trx
|
||||
# flutter-json
|
||||
# golang-json
|
||||
# java-junit
|
||||
# jest-junit
|
||||
# mocha-json
|
||||
|
|
@ -278,6 +280,13 @@ For more information see:
|
|||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>golang-json</summary>
|
||||
|
||||
You must use the `-json` flag and output the results to a file (ex: `go test -json > testresults.json`)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>java-junit (Experimental)</summary>
|
||||
|
||||
|
|
|
|||
38
__tests__/__outputs__/golang-json.md
Normal file
38
__tests__/__outputs__/golang-json.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||

|
||||
|Report|Passed|Failed|Skipped|Time|
|
||||
|:---|---:|---:|---:|---:|
|
||||
|fixtures/golang-json.json|5 ✅|6 ❌|1 ⚪|6s|
|
||||
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/golang-json.json</a>
|
||||
**12** tests were completed in **6s** with **5** passed, **6** failed and **1** skipped.
|
||||
|Test suite|Passed|Failed|Skipped|Time|
|
||||
|:---|---:|---:|---:|---:|
|
||||
|[_/home/james_t/git/test-reporter/reports/go](#user-content-r0s0)|5 ✅|6 ❌|1 ⚪|6s|
|
||||
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">_/home/james_t/git/test-reporter/reports/go</a>
|
||||
```
|
||||
✅ TestPassing
|
||||
❌ TestFailing
|
||||
calculator_test.go:19: expected 1+1 = 3, got 2
|
||||
|
||||
❌ TestPanicInsideFunction
|
||||
calculator_test.go:76: caught panic: runtime error: integer divide by zero
|
||||
|
||||
❌ TestPanicInsideTest
|
||||
calculator_test.go:76: caught panic: bad stuff
|
||||
|
||||
⚪ TestSkipped
|
||||
calculator_test.go:45: skipping test
|
||||
|
||||
❌ TestCases
|
||||
|
||||
TestCases
|
||||
✅ 1_+_2_=_3
|
||||
✅ 4_+_7_=_11
|
||||
❌ 2_+_3_=_4
|
||||
calculator_test.go:67: expected 2 + 3 = 4, got 5
|
||||
|
||||
❌ 1_/_2_=_1
|
||||
calculator_test.go:67: expected 1 / 2 = 1, got 0
|
||||
|
||||
✅ 9_/_3_=_3
|
||||
✅ 14_/_7_=_2
|
||||
```
|
||||
131
__tests__/__snapshots__/golang-json.test.ts.snap
Normal file
131
__tests__/__snapshots__/golang-json.test.ts.snap
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`golang-json tests report from ./reports/dotnet test results matches snapshot 1`] = `
|
||||
TestRunResult {
|
||||
"path": "fixtures/golang-json.json",
|
||||
"suites": [
|
||||
TestSuiteResult {
|
||||
"groups": [
|
||||
TestGroupResult {
|
||||
"name": null,
|
||||
"tests": [
|
||||
TestCaseResult {
|
||||
"error": undefined,
|
||||
"name": "TestPassing",
|
||||
"result": "success",
|
||||
"time": 60,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "calculator_test.go:19: expected 1+1 = 3, got 2
|
||||
",
|
||||
"message": "calculator_test.go:19: expected 1+1 = 3, got 2
|
||||
",
|
||||
},
|
||||
"name": "TestFailing",
|
||||
"result": "failed",
|
||||
"time": 890,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "calculator_test.go:76: caught panic: runtime error: integer divide by zero
|
||||
",
|
||||
"message": "calculator_test.go:76: caught panic: runtime error: integer divide by zero
|
||||
",
|
||||
},
|
||||
"name": "TestPanicInsideFunction",
|
||||
"result": "failed",
|
||||
"time": 0,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "calculator_test.go:76: caught panic: bad stuff
|
||||
",
|
||||
"message": "calculator_test.go:76: caught panic: bad stuff
|
||||
",
|
||||
},
|
||||
"name": "TestPanicInsideTest",
|
||||
"result": "failed",
|
||||
"time": 0,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "calculator_test.go:45: skipping test
|
||||
",
|
||||
"message": "calculator_test.go:45: skipping test
|
||||
",
|
||||
},
|
||||
"name": "TestSkipped",
|
||||
"result": "skipped",
|
||||
"time": 940,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "",
|
||||
"message": "",
|
||||
},
|
||||
"name": "TestCases",
|
||||
"result": "failed",
|
||||
"time": 2250,
|
||||
},
|
||||
],
|
||||
},
|
||||
TestGroupResult {
|
||||
"name": "TestCases",
|
||||
"tests": [
|
||||
TestCaseResult {
|
||||
"error": undefined,
|
||||
"name": "1_+_2_=_3",
|
||||
"result": "success",
|
||||
"time": 400,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": undefined,
|
||||
"name": "4_+_7_=_11",
|
||||
"result": "success",
|
||||
"time": 460,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "calculator_test.go:67: expected 2 + 3 = 4, got 5
|
||||
",
|
||||
"message": "calculator_test.go:67: expected 2 + 3 = 4, got 5
|
||||
",
|
||||
},
|
||||
"name": "2_+_3_=_4",
|
||||
"result": "failed",
|
||||
"time": 90,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": {
|
||||
"details": "calculator_test.go:67: expected 1 / 2 = 1, got 0
|
||||
",
|
||||
"message": "calculator_test.go:67: expected 1 / 2 = 1, got 0
|
||||
",
|
||||
},
|
||||
"name": "1_/_2_=_1",
|
||||
"result": "failed",
|
||||
"time": 920,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": undefined,
|
||||
"name": "9_/_3_=_3",
|
||||
"result": "success",
|
||||
"time": 340,
|
||||
},
|
||||
TestCaseResult {
|
||||
"error": undefined,
|
||||
"name": "14_/_7_=_2",
|
||||
"result": "success",
|
||||
"time": 40,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"name": "_/home/james_t/git/test-reporter/reports/go",
|
||||
"totalTime": undefined,
|
||||
},
|
||||
],
|
||||
"totalTime": undefined,
|
||||
}
|
||||
`;
|
||||
59
__tests__/fixtures/golang-json.json
Normal file
59
__tests__/fixtures/golang-json.json
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{"Time":"2025-04-22T08:59:55.364618802-05:00","Action":"start","Package":"_/home/james_t/git/test-reporter/reports/go"}
|
||||
{"Time":"2025-04-22T08:59:55.371779289-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing"}
|
||||
{"Time":"2025-04-22T08:59:55.371805677-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Output":"=== RUN TestPassing\n"}
|
||||
{"Time":"2025-04-22T08:59:55.428201983-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Output":" calculator_test.go:11: pass!\n"}
|
||||
{"Time":"2025-04-22T08:59:55.428265529-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Output":"--- PASS: TestPassing (0.06s)\n"}
|
||||
{"Time":"2025-04-22T08:59:55.428285649-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Elapsed":0.06}
|
||||
{"Time":"2025-04-22T08:59:55.428299886-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing"}
|
||||
{"Time":"2025-04-22T08:59:55.428309029-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Output":"=== RUN TestFailing\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317425091-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Output":" calculator_test.go:19: expected 1+1 = 3, got 2\n"}
|
||||
{"Time":"2025-04-22T08:59:56.31748077-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Output":"--- FAIL: TestFailing (0.89s)\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317493452-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Elapsed":0.89}
|
||||
{"Time":"2025-04-22T08:59:56.317506107-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction"}
|
||||
{"Time":"2025-04-22T08:59:56.317514487-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Output":"=== RUN TestPanicInsideFunction\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317530448-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Output":" calculator_test.go:76: caught panic: runtime error: integer divide by zero\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317541866-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Output":"--- FAIL: TestPanicInsideFunction (0.00s)\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317552981-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Elapsed":0}
|
||||
{"Time":"2025-04-22T08:59:56.317561057-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest"}
|
||||
{"Time":"2025-04-22T08:59:56.317568742-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Output":"=== RUN TestPanicInsideTest\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317584113-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Output":" calculator_test.go:76: caught panic: bad stuff\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317598524-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Output":"--- FAIL: TestPanicInsideTest (0.00s)\n"}
|
||||
{"Time":"2025-04-22T08:59:56.317608268-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Elapsed":0}
|
||||
{"Time":"2025-04-22T08:59:56.317615472-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped"}
|
||||
{"Time":"2025-04-22T08:59:56.317623959-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Output":"=== RUN TestSkipped\n"}
|
||||
{"Time":"2025-04-22T08:59:57.256475698-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Output":" calculator_test.go:45: skipping test\n"}
|
||||
{"Time":"2025-04-22T08:59:57.256536372-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Output":"--- SKIP: TestSkipped (0.94s)\n"}
|
||||
{"Time":"2025-04-22T08:59:57.256549142-05:00","Action":"skip","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Elapsed":0.94}
|
||||
{"Time":"2025-04-22T08:59:57.256562053-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases"}
|
||||
{"Time":"2025-04-22T08:59:57.256569388-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases","Output":"=== RUN TestCases\n"}
|
||||
{"Time":"2025-04-22T08:59:57.256580104-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3"}
|
||||
{"Time":"2025-04-22T08:59:57.256587408-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3","Output":"=== RUN TestCases/1_+_2_=_3\n"}
|
||||
{"Time":"2025-04-22T08:59:57.653005399-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11"}
|
||||
{"Time":"2025-04-22T08:59:57.653036336-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11","Output":"=== RUN TestCases/4_+_7_=_11\n"}
|
||||
{"Time":"2025-04-22T08:59:58.112825221-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4"}
|
||||
{"Time":"2025-04-22T08:59:58.112858016-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Output":"=== RUN TestCases/2_+_3_=_4\n"}
|
||||
{"Time":"2025-04-22T08:59:58.201204209-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Output":" calculator_test.go:67: expected 2 + 3 = 4, got 5\n"}
|
||||
{"Time":"2025-04-22T08:59:58.201245827-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1"}
|
||||
{"Time":"2025-04-22T08:59:58.201255566-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Output":"=== RUN TestCases/1_/_2_=_1\n"}
|
||||
{"Time":"2025-04-22T08:59:59.119852965-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Output":" calculator_test.go:67: expected 1 / 2 = 1, got 0\n"}
|
||||
{"Time":"2025-04-22T08:59:59.119877603-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3"}
|
||||
{"Time":"2025-04-22T08:59:59.119879955-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3","Output":"=== RUN TestCases/9_/_3_=_3\n"}
|
||||
{"Time":"2025-04-22T08:59:59.460576385-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2"}
|
||||
{"Time":"2025-04-22T08:59:59.460607599-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2","Output":"=== RUN TestCases/14_/_7_=_2\n"}
|
||||
{"Time":"2025-04-22T08:59:59.504952672-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases","Output":"--- FAIL: TestCases (2.25s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.504995938-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3","Output":" --- PASS: TestCases/1_+_2_=_3 (0.40s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505006062-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3","Elapsed":0.4}
|
||||
{"Time":"2025-04-22T08:59:59.505017551-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11","Output":" --- PASS: TestCases/4_+_7_=_11 (0.46s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505026099-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11","Elapsed":0.46}
|
||||
{"Time":"2025-04-22T08:59:59.505033963-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Output":" --- FAIL: TestCases/2_+_3_=_4 (0.09s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505042238-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Elapsed":0.09}
|
||||
{"Time":"2025-04-22T08:59:59.505050917-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Output":" --- FAIL: TestCases/1_/_2_=_1 (0.92s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505059901-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Elapsed":0.92}
|
||||
{"Time":"2025-04-22T08:59:59.505068125-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3","Output":" --- PASS: TestCases/9_/_3_=_3 (0.34s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505076976-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3","Elapsed":0.34}
|
||||
{"Time":"2025-04-22T08:59:59.5050845-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2","Output":" --- PASS: TestCases/14_/_7_=_2 (0.04s)\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505091554-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2","Elapsed":0.04}
|
||||
{"Time":"2025-04-22T08:59:59.505098998-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases","Elapsed":2.25}
|
||||
{"Time":"2025-04-22T08:59:59.505107502-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Output":"FAIL\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505552861-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Output":"FAIL\t_/home/james_t/git/test-reporter/reports/go\t4.141s\n"}
|
||||
{"Time":"2025-04-22T08:59:59.505584529-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Elapsed":4.141}
|
||||
29
__tests__/golang-json.test.ts
Normal file
29
__tests__/golang-json.test.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
|
||||
import {GolangJsonParser} from '../src/parsers/golang-json/golang-json-parser'
|
||||
import {ParseOptions} from '../src/test-parser'
|
||||
import {getReport} from '../src/report/get-report'
|
||||
import {normalizeFilePath} from '../src/utils/path-utils'
|
||||
|
||||
describe('golang-json tests', () => {
|
||||
it('report from ./reports/dotnet test results matches snapshot', async () => {
|
||||
const fixturePath = path.join(__dirname, 'fixtures', 'golang-json.json')
|
||||
const outputPath = path.join(__dirname, '__outputs__', 'golang-json.md')
|
||||
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||
|
||||
const opts: ParseOptions = {
|
||||
parseErrors: true,
|
||||
trackedFiles: ['calculator.go', 'calculator_test.go']
|
||||
}
|
||||
|
||||
const parser = new GolangJsonParser(opts)
|
||||
const result = await parser.parse(filePath, fileContent)
|
||||
expect(result).toMatchSnapshot()
|
||||
|
||||
const report = getReport([result])
|
||||
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
|
||||
fs.writeFileSync(outputPath, report)
|
||||
})
|
||||
})
|
||||
103
dist/index.js
generated
vendored
103
dist/index.js
generated
vendored
|
|
@ -273,6 +273,7 @@ const get_report_1 = __nccwpck_require__(7070);
|
|||
const dart_json_parser_1 = __nccwpck_require__(1254);
|
||||
const dotnet_nunit_parser_1 = __nccwpck_require__(6394);
|
||||
const dotnet_trx_parser_1 = __nccwpck_require__(1658);
|
||||
const golang_json_parser_1 = __nccwpck_require__(5162);
|
||||
const java_junit_parser_1 = __nccwpck_require__(8342);
|
||||
const jest_junit_parser_1 = __nccwpck_require__(1042);
|
||||
const mocha_json_parser_1 = __nccwpck_require__(5402);
|
||||
|
|
@ -475,6 +476,8 @@ class TestReporter {
|
|||
return new dotnet_nunit_parser_1.DotnetNunitParser(options);
|
||||
case 'dotnet-trx':
|
||||
return new dotnet_trx_parser_1.DotnetTrxParser(options);
|
||||
case 'golang-json':
|
||||
return new golang_json_parser_1.GolangJsonParser(options);
|
||||
case 'flutter-json':
|
||||
return new dart_json_parser_1.DartJsonParser(options, 'flutter');
|
||||
case 'java-junit':
|
||||
|
|
@ -1066,6 +1069,106 @@ class DotnetTrxParser {
|
|||
exports.DotnetTrxParser = DotnetTrxParser;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 5162:
|
||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.GolangJsonParser = void 0;
|
||||
const test_results_1 = __nccwpck_require__(613);
|
||||
class GolangJsonParser {
|
||||
options;
|
||||
assumedWorkDir;
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
}
|
||||
async parse(path, content) {
|
||||
const events = await this.getGolangTestEvents(path, content);
|
||||
return this.getTestRunResult(path, events);
|
||||
}
|
||||
async getGolangTestEvents(path, content) {
|
||||
return content.trim().split('\n').map((line, index) => {
|
||||
try {
|
||||
return JSON.parse(line);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Invalid JSON at ${path} line ${index + 1}\n\n${e}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
getTestRunResult(path, events) {
|
||||
const eventGroups = new Map();
|
||||
for (const event of events) {
|
||||
if (!event.Test) {
|
||||
continue;
|
||||
}
|
||||
const k = `${event.Package}/${event.Test}`;
|
||||
let g = eventGroups.get(k);
|
||||
if (!g) {
|
||||
g = [];
|
||||
eventGroups.set(k, g);
|
||||
}
|
||||
g.push(event);
|
||||
}
|
||||
const suites = [];
|
||||
for (const eventGroup of eventGroups.values()) {
|
||||
const event = eventGroup[0];
|
||||
let suite = suites.find(s => s.name === event.Package);
|
||||
if (!suite) {
|
||||
suite = new test_results_1.TestSuiteResult(event.Package, []);
|
||||
suites.push(suite);
|
||||
}
|
||||
if (!event.Test) {
|
||||
continue;
|
||||
}
|
||||
let groupName;
|
||||
let rest;
|
||||
[groupName, ...rest] = event.Test.split('/');
|
||||
let testName = rest.join('/');
|
||||
if (!testName) {
|
||||
testName = groupName;
|
||||
groupName = null;
|
||||
}
|
||||
let group = suite.groups.find(g => g.name === groupName);
|
||||
if (!group) {
|
||||
group = new test_results_1.TestGroupResult(groupName, []);
|
||||
suite.groups.push(group);
|
||||
}
|
||||
const lastEvent = eventGroup.at(-1);
|
||||
const result = lastEvent.Action === 'pass' ? 'success'
|
||||
: lastEvent.Action === 'skip' ? 'skipped'
|
||||
: 'failed';
|
||||
if (lastEvent.Elapsed === undefined) {
|
||||
throw new Error('missing elapsed on final test event');
|
||||
}
|
||||
const time = lastEvent.Elapsed * 1000;
|
||||
let error = undefined;
|
||||
if (result !== 'success') {
|
||||
const outputEvents = eventGroup
|
||||
.filter(e => e.Action === 'output')
|
||||
.map(e => e.Output ?? '')
|
||||
// Go output prepends indentation to help group tests - remove it
|
||||
.map(o => o.replace(/^ /, ''));
|
||||
// First and last lines will be generic "test started" and "test finished" lines - remove them
|
||||
outputEvents.splice(0, 1);
|
||||
outputEvents.splice(-1, 1);
|
||||
const details = outputEvents.join('');
|
||||
error = {
|
||||
message: details,
|
||||
details: details
|
||||
};
|
||||
}
|
||||
group.tests.push(new test_results_1.TestCaseResult(testName, result, time, error));
|
||||
}
|
||||
return new test_results_1.TestRunResult(path, suites);
|
||||
}
|
||||
}
|
||||
exports.GolangJsonParser = GolangJsonParser;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8342:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
"dart-fixture": "cd \"reports/dart\" && dart test --file-reporter=\"json:../../__tests__/fixtures/dart-json.json\"",
|
||||
"dotnet-fixture": "dotnet test reports/dotnet/DotnetTests.XUnitTests --logger \"trx;LogFileName=../../../../__tests__/fixtures/dotnet-trx.trx\"",
|
||||
"dotnet-nunit-fixture": "nunit.exe reports/dotnet/DotnetTests.NUnitV3Tests/bin/Debug/netcoreapp3.1/DotnetTests.NUnitV3Tests.dll --result=__tests__/fixtures/dotnet-nunit.xml",
|
||||
"dotnet-nunit-legacy-fixture": "nunit-console.exe reports/dotnet-nunit-legacy/NUnitLegacy.sln --result=__tests__/fixtures/dotnet-nunit-legacy.xml",
|
||||
"golang-json-fixture": "go test -v -json -timeout 5s ./reports/go | tee __tests__/fixtures/golang-json.json",
|
||||
"jest-fixture": "cd \"reports/jest\" && npm test",
|
||||
"mocha-fixture": "cd \"reports/mocha\" && npm test"
|
||||
},
|
||||
|
|
|
|||
20
reports/go/calculator.go
Normal file
20
reports/go/calculator.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
func CalculatorSum(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func CalculatorDivide(a, b int) int {
|
||||
return a / b
|
||||
}
|
||||
|
||||
var ErrDivideByZero = errors.New("divide by zero")
|
||||
|
||||
func CalculatorSafeDivide(a, b int) (int, error) {
|
||||
if b == 0 {
|
||||
return 0, ErrDivideByZero
|
||||
}
|
||||
return a / b, nil
|
||||
}
|
||||
82
reports/go/calculator_test.go
Normal file
82
reports/go/calculator_test.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPassing(t *testing.T) {
|
||||
randomSleep()
|
||||
t.Log("pass!")
|
||||
}
|
||||
|
||||
func TestFailing(t *testing.T) {
|
||||
randomSleep()
|
||||
expected := 3
|
||||
actual := CalculatorSum(1, 1)
|
||||
if actual != expected {
|
||||
t.Fatalf("expected 1+1 = %d, got %d", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicInsideFunction(t *testing.T) {
|
||||
defer catchPanics(t)
|
||||
|
||||
expected := 0
|
||||
actual := CalculatorDivide(1, 0)
|
||||
if actual != expected {
|
||||
t.Fatalf("expected 1/1 = %d, got %d", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicInsideTest(t *testing.T) {
|
||||
defer catchPanics(t)
|
||||
panic("bad stuff")
|
||||
}
|
||||
|
||||
// Timeouts cause the entire test process to end - so we can't get good output for these
|
||||
// func TestTimeout(t *testing.T) {
|
||||
// time.Sleep(time.Second * 5)
|
||||
// }
|
||||
|
||||
func TestSkipped(t *testing.T) {
|
||||
randomSleep()
|
||||
t.Skipf("skipping test")
|
||||
}
|
||||
|
||||
func TestCases(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
fn func(int, int) int
|
||||
a, b, c int
|
||||
}{
|
||||
{"1 + 2 = 3", CalculatorSum, 1, 2, 3},
|
||||
{"4 + 7 = 11", CalculatorSum, 4, 7, 11},
|
||||
{"2 + 3 = 4", CalculatorSum, 2, 3, 4},
|
||||
|
||||
{"1 / 2 = 1", CalculatorDivide, 1, 2, 1},
|
||||
{"9 / 3 = 3", CalculatorDivide, 9, 3, 3},
|
||||
{"14 / 7 = 2", CalculatorDivide, 14, 7, 2},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
randomSleep()
|
||||
|
||||
c := tc.fn(tc.a, tc.b)
|
||||
if c != tc.c {
|
||||
t.Fatalf("expected %s, got %d", tc.name, c)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func catchPanics(t *testing.T) {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
t.Fatalf("caught panic: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func randomSleep() {
|
||||
time.Sleep(time.Duration(rand.Int63n(int64(time.Second))))
|
||||
}
|
||||
3
reports/go/go.mod
Normal file
3
reports/go/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module test_reporter_example
|
||||
|
||||
go 1.24.2
|
||||
|
|
@ -13,6 +13,7 @@ import {getReport} from './report/get-report'
|
|||
import {DartJsonParser} from './parsers/dart-json/dart-json-parser'
|
||||
import {DotnetNunitParser} from './parsers/dotnet-nunit/dotnet-nunit-parser'
|
||||
import {DotnetTrxParser} from './parsers/dotnet-trx/dotnet-trx-parser'
|
||||
import {GolangJsonParser} from './parsers/golang-json/golang-json-parser'
|
||||
import {JavaJunitParser} from './parsers/java-junit/java-junit-parser'
|
||||
import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser'
|
||||
import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser'
|
||||
|
|
@ -248,6 +249,8 @@ class TestReporter {
|
|||
return new DotnetNunitParser(options)
|
||||
case 'dotnet-trx':
|
||||
return new DotnetTrxParser(options)
|
||||
case 'golang-json':
|
||||
return new GolangJsonParser(options)
|
||||
case 'flutter-json':
|
||||
return new DartJsonParser(options, 'flutter')
|
||||
case 'java-junit':
|
||||
|
|
|
|||
115
src/parsers/golang-json/golang-json-parser.ts
Normal file
115
src/parsers/golang-json/golang-json-parser.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import { ParseOptions, TestParser } from '../../test-parser'
|
||||
|
||||
import { GoTestEvent } from './golang-json-types'
|
||||
import { getExceptionSource } from '../../utils/node-utils'
|
||||
import { getBasePath, normalizeFilePath } from '../../utils/path-utils'
|
||||
|
||||
import {
|
||||
TestExecutionResult,
|
||||
TestRunResult,
|
||||
TestSuiteResult,
|
||||
TestGroupResult,
|
||||
TestCaseResult,
|
||||
TestCaseError
|
||||
} from '../../test-results'
|
||||
|
||||
export class GolangJsonParser implements TestParser {
|
||||
assumedWorkDir: string | undefined
|
||||
|
||||
constructor(readonly options: ParseOptions) { }
|
||||
|
||||
async parse(path: string, content: string): Promise<TestRunResult> {
|
||||
const events = await this.getGolangTestEvents(path, content)
|
||||
return this.getTestRunResult(path, events)
|
||||
}
|
||||
|
||||
private async getGolangTestEvents(path: string, content: string): Promise<GoTestEvent[]> {
|
||||
return content.trim().split('\n').map((line, index) => {
|
||||
try {
|
||||
return JSON.parse(line) as GoTestEvent
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON at ${path} line ${index + 1}\n\n${e}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private getTestRunResult(path: string, events: GoTestEvent[]): TestRunResult {
|
||||
const eventGroups = new Map<string, GoTestEvent[]>()
|
||||
for (const event of events) {
|
||||
if (!event.Test) {
|
||||
continue
|
||||
}
|
||||
const k = `${event.Package}/${event.Test}`
|
||||
let g = eventGroups.get(k)
|
||||
if (!g) {
|
||||
g = []
|
||||
eventGroups.set(k, g)
|
||||
}
|
||||
g.push(event)
|
||||
}
|
||||
|
||||
const suites: TestSuiteResult[] = []
|
||||
|
||||
for (const eventGroup of eventGroups.values()) {
|
||||
const event = eventGroup[0]
|
||||
|
||||
let suite = suites.find(s => s.name === event.Package)
|
||||
if (!suite) {
|
||||
suite = new TestSuiteResult(event.Package, [])
|
||||
suites.push(suite)
|
||||
}
|
||||
|
||||
if (!event.Test) {
|
||||
continue
|
||||
}
|
||||
|
||||
let groupName: string | null
|
||||
let rest: string[]
|
||||
[groupName, ...rest] = event.Test.split('/')
|
||||
let testName = rest.join('/')
|
||||
if (!testName) {
|
||||
testName = groupName
|
||||
groupName = null
|
||||
}
|
||||
|
||||
let group = suite.groups.find(g => g.name === groupName)
|
||||
if (!group) {
|
||||
group = new TestGroupResult(groupName, [])
|
||||
suite.groups.push(group)
|
||||
}
|
||||
|
||||
const lastEvent = eventGroup.at(-1)!
|
||||
|
||||
const result: TestExecutionResult = lastEvent.Action === 'pass' ? 'success'
|
||||
: lastEvent.Action === 'skip' ? 'skipped'
|
||||
: 'failed'
|
||||
if (lastEvent.Elapsed === undefined) {
|
||||
throw new Error('missing elapsed on final test event')
|
||||
}
|
||||
const time: number = lastEvent.Elapsed * 1000
|
||||
|
||||
let error: TestCaseError | undefined = undefined
|
||||
if (result !== 'success') {
|
||||
const outputEvents = eventGroup
|
||||
.filter(e => e.Action === 'output')
|
||||
.map(e => e.Output ?? '')
|
||||
// Go output prepends indentation to help group tests - remove it
|
||||
.map(o => o.replace(/^ /, ''))
|
||||
|
||||
// First and last lines will be generic "test started" and "test finished" lines - remove them
|
||||
outputEvents.splice(0, 1)
|
||||
outputEvents.splice(-1, 1)
|
||||
|
||||
const details = outputEvents.join('')
|
||||
error = {
|
||||
message: details,
|
||||
details: details
|
||||
}
|
||||
}
|
||||
|
||||
group.tests.push(new TestCaseResult(testName, result, time, error))
|
||||
}
|
||||
|
||||
return new TestRunResult(path, suites)
|
||||
}
|
||||
}
|
||||
19
src/parsers/golang-json/golang-json-types.ts
Normal file
19
src/parsers/golang-json/golang-json-types.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
export type GoTestAction = 'start'
|
||||
| 'run'
|
||||
| 'pause'
|
||||
| 'cont'
|
||||
| 'pass'
|
||||
| 'bench'
|
||||
| 'fail'
|
||||
| 'output'
|
||||
| 'skip'
|
||||
|
||||
export type GoTestEvent = {
|
||||
Time: string
|
||||
Action: GoTestAction
|
||||
Package: string
|
||||
Test?: string
|
||||
Elapsed?: number
|
||||
Output?: string
|
||||
FailedBuild?: string
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue