Skip to content

Commit d050604

Browse files
authoredDec 5, 2022
fix: add test attributes to "testsuites" in junit reporter (#2362)
* fix: add test attributes to "testcases" in junit reporter * docs: add information about VITEST_JUNIT_SUITE_NAME
1 parent 32cc1a6 commit d050604

File tree

5 files changed

+34
-16
lines changed

5 files changed

+34
-16
lines changed
 

‎docs/config/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ Custom reporters for output. Reporters can be [a Reporter instance](https://gith
339339
- `'default'` - collapse suites when they pass
340340
- `'verbose'` - keep the full task tree visible
341341
- `'dot'` - show each task as a single dot
342-
- `'junit'` - JUnit XML reporter
342+
- `'junit'` - JUnit XML reporter (you can configure `testsuites` tag name with `VITEST_JUNIT_SUITE_NAME` environmental variable)
343343
- `'json'` - give a simple JSON summary
344344
- path of a custom reporter (e.g. `'./path/to/reporter.ts'`, `'@scope/reporter'`)
345345

‎packages/vitest/src/node/reporters/junit.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,21 @@ function escapeXML(value: any): string {
5858
true)
5959
}
6060

61+
function executionTime(durationMS: number) {
62+
return (durationMS / 1000).toLocaleString(undefined, { useGrouping: false, maximumFractionDigits: 10 })
63+
}
64+
6165
export function getDuration(task: Task): string | undefined {
6266
const duration = task.result?.duration ?? 0
63-
return (duration / 1000).toLocaleString(undefined, { useGrouping: false, maximumFractionDigits: 10 })
67+
return executionTime(duration)
6468
}
6569

6670
export class JUnitReporter implements Reporter {
6771
private ctx!: Vitest
6872
private reportFile?: string
6973
private baseLog!: (text: string) => Promise<void>
7074
private logger!: IndentedLogger<Promise<void>>
75+
private _timeStart = new Date()
7176

7277
async onInit(ctx: Vitest): Promise<void> {
7378
this.ctx = ctx
@@ -89,6 +94,7 @@ export class JUnitReporter implements Reporter {
8994
this.baseLog = async (text: string) => this.ctx.logger.log(text)
9095
}
9196

97+
this._timeStart = new Date()
9298
this.logger = new IndentedLogger(this.baseLog)
9399
}
94100

@@ -205,7 +211,19 @@ export class JUnitReporter implements Reporter {
205211
}
206212
})
207213

208-
await this.writeElement('testsuites', {}, async () => {
214+
const stats = transformed.reduce((stats, file) => {
215+
stats.tests += file.tasks.length
216+
stats.failures += file.stats.failures
217+
return stats
218+
}, {
219+
name: process.env.VITEST_JUNIT_SUITE_NAME || 'vitest tests',
220+
tests: 0,
221+
failures: 0,
222+
errors: 0, // we cannot detect those
223+
time: executionTime(new Date().getTime() - this._timeStart.getTime()),
224+
})
225+
226+
await this.writeElement('testsuites', stats, async () => {
209227
for (const file of transformed) {
210228
await this.writeElement('testsuite', {
211229
name: file.name,

‎test/reporters/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@vitest/test-reporters",
33
"private": true,
44
"scripts": {
5-
"test": "vitest"
5+
"test": "vitest run"
66
},
77
"devDependencies": {
88
"execa": "^6.1.0",

‎test/reporters/tests/__snapshots__/reporters.spec.ts.snap

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
exports[`JUnit reporter (no outputFile entry) 1`] = `
44
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
5-
<testsuites>
5+
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
66
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"2\\" time=\\"0.145992842\\">
77
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
88
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
@@ -38,7 +38,7 @@ AssertionError: expected 2.23606797749979 to equal 2
3838
3939
exports[`JUnit reporter 1`] = `
4040
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
41-
<testsuites>
41+
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
4242
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"2\\" time=\\"0.145992842\\">
4343
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
4444
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
@@ -79,7 +79,7 @@ exports[`JUnit reporter with outputFile 1`] = `
7979
8080
exports[`JUnit reporter with outputFile 2`] = `
8181
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
82-
<testsuites>
82+
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
8383
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"2\\" time=\\"0.145992842\\">
8484
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
8585
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
@@ -120,7 +120,7 @@ exports[`JUnit reporter with outputFile in non-existing directory 1`] = `
120120
121121
exports[`JUnit reporter with outputFile in non-existing directory 2`] = `
122122
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
123-
<testsuites>
123+
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
124124
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"2\\" time=\\"0.145992842\\">
125125
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
126126
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
@@ -161,7 +161,7 @@ exports[`JUnit reporter with outputFile object 1`] = `
161161
162162
exports[`JUnit reporter with outputFile object 2`] = `
163163
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
164-
<testsuites>
164+
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
165165
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"2\\" time=\\"0.145992842\\">
166166
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
167167
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
@@ -202,7 +202,7 @@ exports[`JUnit reporter with outputFile object in non-existing directory 1`] = `
202202
203203
exports[`JUnit reporter with outputFile object in non-existing directory 2`] = `
204204
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
205-
<testsuites>
205+
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
206206
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"2\\" time=\\"0.145992842\\">
207207
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
208208
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
@@ -243,7 +243,7 @@ exports[`JUnit reporter with outputFile with XML in error message 1`] = `
243243
244244
exports[`JUnit reporter with outputFile with XML in error message 2`] = `
245245
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
246-
<testsuites>
246+
<testsuites name=\\"vitest tests\\" tests=\\"1\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
247247
<testsuite name=\\"test/core/test/basic.test.ts\\" timestamp=\\"2022-01-19T10:10:01.759Z\\" hostname=\\"hostname\\" tests=\\"1\\" failures=\\"1\\" errors=\\"0\\" skipped=\\"0\\" time=\\"0.145992842\\">
248248
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; test with xml in error\\" time=\\"0.0021231231\\">
249249
<failure message=\\"error message that has XML in it &lt;tag&gt;\\" type=\\"AssertionError\\">

‎test/reporters/tests/reporters.spec.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { existsSync, readFileSync, rmSync, rmdirSync } from 'fs'
1+
import { existsSync, readFileSync, rmSync } from 'fs'
22
import { afterEach, expect, test, vi } from 'vitest'
33
import { normalize, resolve } from 'pathe'
44
import { JsonReporter } from '../../../packages/vitest/src/node/reporters/json'
@@ -185,7 +185,7 @@ test('JUnit reporter with outputFile in non-existing directory', async () => {
185185
expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()
186186

187187
// Cleanup
188-
rmdirSync(rootDirectory, { recursive: true })
188+
rmSync(rootDirectory, { recursive: true })
189189
})
190190

191191
test('JUnit reporter with outputFile object in non-existing directory', async () => {
@@ -214,7 +214,7 @@ test('JUnit reporter with outputFile object in non-existing directory', async ()
214214
expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()
215215

216216
// Cleanup
217-
rmdirSync(rootDirectory, { recursive: true })
217+
rmSync(rootDirectory, { recursive: true })
218218
})
219219

220220
test('json reporter', async () => {
@@ -314,7 +314,7 @@ test('json reporter with outputFile in non-existing directory', async () => {
314314
expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()
315315

316316
// Cleanup
317-
rmdirSync(rootDirectory, { recursive: true })
317+
rmSync(rootDirectory, { recursive: true })
318318
})
319319

320320
test('json reporter with outputFile object in non-existing directory', async () => {
@@ -339,7 +339,7 @@ test('json reporter with outputFile object in non-existing directory', async ()
339339
expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()
340340

341341
// Cleanup
342-
rmdirSync(rootDirectory, { recursive: true })
342+
rmSync(rootDirectory, { recursive: true })
343343
})
344344

345345
/**

0 commit comments

Comments
 (0)
Please sign in to comment.