From ca37a06aadc038537786929df8da4e766a968b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20=E3=82=B5=E3=82=A4=E3=83=88=E3=83=BC=20=E4=B8=AD?= =?UTF-8?q?=E6=9D=91=20Bashurov?= Date: Tue, 3 Dec 2024 10:55:29 +0200 Subject: [PATCH] fix(junit): fix testsuites time to be sum of all testsuite items (#6985) --- packages/vitest/src/node/reporters/junit.ts | 5 +-- .../__snapshots__/reporters.spec.ts.snap | 8 ++--- test/reporters/tests/junit.test.ts | 34 +++++++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/vitest/src/node/reporters/junit.ts b/packages/vitest/src/node/reporters/junit.ts index d6185813d133..86789b802090 100644 --- a/packages/vitest/src/node/reporters/junit.ts +++ b/packages/vitest/src/node/reporters/junit.ts @@ -335,6 +335,7 @@ export class JUnitReporter implements Reporter { (stats, file) => { stats.tests += file.tasks.length stats.failures += file.stats.failures + stats.time += file.result?.duration || 0 return stats }, { @@ -342,11 +343,11 @@ export class JUnitReporter implements Reporter { tests: 0, failures: 0, errors: 0, // we cannot detect those - time: executionTime(new Date().getTime() - this._timeStart.getTime()), + time: 0, }, ) - await this.writeElement('testsuites', stats, async () => { + await this.writeElement('testsuites', { ...stats, time: executionTime(stats.time) }, async () => { for (const file of transformed) { const filename = relative(this.ctx.config.root, file.filepath) await this.writeElement( diff --git a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap index bf21bff29f27..c9965e6e9073 100644 --- a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap +++ b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap @@ -16,7 +16,7 @@ exports[`JUnit reporter 1`] = ` exports[`JUnit reporter with custom function classnameTemplate 1`] = ` " - + @@ -27,7 +27,7 @@ exports[`JUnit reporter with custom function classnameTemplate 1`] = ` exports[`JUnit reporter with custom string classname 1`] = ` " - + @@ -38,7 +38,7 @@ exports[`JUnit reporter with custom string classname 1`] = ` exports[`JUnit reporter with custom string classnameTemplate 1`] = ` " - + @@ -97,7 +97,7 @@ exports[`JUnit reporter with outputFile object in non-existing directory 2`] = ` exports[`JUnit reporter without classname 1`] = ` " - + diff --git a/test/reporters/tests/junit.test.ts b/test/reporters/tests/junit.test.ts index 48da15ee0142..6b9ebfa84422 100644 --- a/test/reporters/tests/junit.test.ts +++ b/test/reporters/tests/junit.test.ts @@ -72,6 +72,28 @@ test('emits when beforeAll/afterAll failed', async () => { expect(xml).toMatchSnapshot() }) +test('time', async () => { + const { stdout } = await runVitest({ reporters: 'junit', root: './fixtures/duration' }) + + const xml = stabilizeReportWOTime(stdout) + + const fastTestRegex = // + const fastTestTime = matchJunitTime(xml, fastTestRegex) + expect(fastTestTime).toBeGreaterThan(0) + + const slowTestRegex = // + const slowTestTime = matchJunitTime(xml, slowTestRegex) + expect(slowTestTime).toBeGreaterThan(0.2) + + const testsuiteRegex = // + const testsuiteTime = matchJunitTime(xml, testsuiteRegex) + expect(testsuiteTime).toBeCloseTo(fastTestTime + slowTestTime, 1) + + const testsuitesRegex = // + const testsuitesTime = matchJunitTime(xml, testsuitesRegex) + expect(testsuitesTime).toBeCloseTo(testsuiteTime, 1) +}) + test('format error', async () => { const { stdout } = await runVitest({ reporters: 'junit', root }, ['error.test.ts']) expect(stabilizeReport(stdout)).toMatchSnapshot() @@ -118,6 +140,18 @@ function stabilizeReport(report: string) { return report.replaceAll(/(timestamp|hostname|time)=".*?"/g, '$1="..."') } +function stabilizeReportWOTime(report: string) { + return report.replaceAll(/(timestamp|hostname)=".*?"/g, '$1="..."') +} + +function matchJunitTime(xml: string, regex: RegExp) { + const match = xml.match(regex) + expect(match).not.toBeNull() + const time = Number.parseFloat(match!.groups!.floatNumber) + expect(time).toBeGreaterThanOrEqual(0) + return time +} + test.each([true, false])('includeConsoleOutput %s', async (t) => { const { stdout } = await runVitest({ reporters: [['junit', { includeConsoleOutput: t }]],