Skip to content

Commit

Permalink
fix: add test attributes to "testsuites" in junit reporter (#2362)
Browse files Browse the repository at this point in the history
* fix: add test attributes to "testcases" in junit reporter

* docs: add information about VITEST_JUNIT_SUITE_NAME
  • Loading branch information
sheremet-va committed Dec 5, 2022
1 parent 32cc1a6 commit d050604
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 16 deletions.
2 changes: 1 addition & 1 deletion docs/config/index.md
Expand Up @@ -339,7 +339,7 @@ Custom reporters for output. Reporters can be [a Reporter instance](https://gith
- `'default'` - collapse suites when they pass
- `'verbose'` - keep the full task tree visible
- `'dot'` - show each task as a single dot
- `'junit'` - JUnit XML reporter
- `'junit'` - JUnit XML reporter (you can configure `testsuites` tag name with `VITEST_JUNIT_SUITE_NAME` environmental variable)
- `'json'` - give a simple JSON summary
- path of a custom reporter (e.g. `'./path/to/reporter.ts'`, `'@scope/reporter'`)

Expand Down
22 changes: 20 additions & 2 deletions packages/vitest/src/node/reporters/junit.ts
Expand Up @@ -58,16 +58,21 @@ function escapeXML(value: any): string {
true)
}

function executionTime(durationMS: number) {
return (durationMS / 1000).toLocaleString(undefined, { useGrouping: false, maximumFractionDigits: 10 })
}

export function getDuration(task: Task): string | undefined {
const duration = task.result?.duration ?? 0
return (duration / 1000).toLocaleString(undefined, { useGrouping: false, maximumFractionDigits: 10 })
return executionTime(duration)
}

export class JUnitReporter implements Reporter {
private ctx!: Vitest
private reportFile?: string
private baseLog!: (text: string) => Promise<void>
private logger!: IndentedLogger<Promise<void>>
private _timeStart = new Date()

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

this._timeStart = new Date()
this.logger = new IndentedLogger(this.baseLog)
}

Expand Down Expand Up @@ -205,7 +211,19 @@ export class JUnitReporter implements Reporter {
}
})

await this.writeElement('testsuites', {}, async () => {
const stats = transformed.reduce((stats, file) => {
stats.tests += file.tasks.length
stats.failures += file.stats.failures
return stats
}, {
name: process.env.VITEST_JUNIT_SUITE_NAME || 'vitest tests',
tests: 0,
failures: 0,
errors: 0, // we cannot detect those
time: executionTime(new Date().getTime() - this._timeStart.getTime()),
})

await this.writeElement('testsuites', stats, async () => {
for (const file of transformed) {
await this.writeElement('testsuite', {
name: file.name,
Expand Down
2 changes: 1 addition & 1 deletion test/reporters/package.json
Expand Up @@ -2,7 +2,7 @@
"name": "@vitest/test-reporters",
"private": true,
"scripts": {
"test": "vitest"
"test": "vitest run"
},
"devDependencies": {
"execa": "^6.1.0",
Expand Down
14 changes: 7 additions & 7 deletions test/reporters/tests/__snapshots__/reporters.spec.ts.snap
Expand Up @@ -2,7 +2,7 @@

exports[`JUnit reporter (no outputFile entry) 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
Expand Down Expand Up @@ -38,7 +38,7 @@ AssertionError: expected 2.23606797749979 to equal 2
exports[`JUnit reporter 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
Expand Down Expand Up @@ -79,7 +79,7 @@ exports[`JUnit reporter with outputFile 1`] = `
exports[`JUnit reporter with outputFile 2`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
Expand Down Expand Up @@ -120,7 +120,7 @@ exports[`JUnit reporter with outputFile in non-existing directory 1`] = `
exports[`JUnit reporter with outputFile in non-existing directory 2`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
Expand Down Expand Up @@ -161,7 +161,7 @@ exports[`JUnit reporter with outputFile object 1`] = `
exports[`JUnit reporter with outputFile object 2`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
Expand Down Expand Up @@ -202,7 +202,7 @@ exports[`JUnit reporter with outputFile object in non-existing directory 1`] = `
exports[`JUnit reporter with outputFile object in non-existing directory 2`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"9\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; inner suite &gt; Math.sqrt()\\" time=\\"0.001442286\\">
<failure message=\\"expected 2.23606797749979 to equal 2\\" type=\\"AssertionError\\">
Expand Down Expand Up @@ -243,7 +243,7 @@ exports[`JUnit reporter with outputFile with XML in error message 1`] = `
exports[`JUnit reporter with outputFile with XML in error message 2`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" ?>
<testsuites>
<testsuites name=\\"vitest tests\\" tests=\\"1\\" failures=\\"1\\" errors=\\"0\\" time=\\"0\\">
<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\\">
<testcase classname=\\"test/core/test/basic.test.ts\\" name=\\"suite &gt; test with xml in error\\" time=\\"0.0021231231\\">
<failure message=\\"error message that has XML in it &lt;tag&gt;\\" type=\\"AssertionError\\">
Expand Down
10 changes: 5 additions & 5 deletions test/reporters/tests/reporters.spec.ts
@@ -1,4 +1,4 @@
import { existsSync, readFileSync, rmSync, rmdirSync } from 'fs'
import { existsSync, readFileSync, rmSync } from 'fs'
import { afterEach, expect, test, vi } from 'vitest'
import { normalize, resolve } from 'pathe'
import { JsonReporter } from '../../../packages/vitest/src/node/reporters/json'
Expand Down Expand Up @@ -185,7 +185,7 @@ test('JUnit reporter with outputFile in non-existing directory', async () => {
expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()

// Cleanup
rmdirSync(rootDirectory, { recursive: true })
rmSync(rootDirectory, { recursive: true })
})

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

// Cleanup
rmdirSync(rootDirectory, { recursive: true })
rmSync(rootDirectory, { recursive: true })
})

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

// Cleanup
rmdirSync(rootDirectory, { recursive: true })
rmSync(rootDirectory, { recursive: true })
})

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

// Cleanup
rmdirSync(rootDirectory, { recursive: true })
rmSync(rootDirectory, { recursive: true })
})

/**
Expand Down

0 comments on commit d050604

Please sign in to comment.