fix(vitest): show beforeAll/afterAll errors in junit reporter (#4819)

This commit is contained in:
Hiroshi Ogawa 2023-12-31 22:26:31 +09:00 committed by GitHub
parent 7e6a62af0a
commit 2baea35e2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 0 deletions

View File

@ -4,6 +4,7 @@ import { dirname, relative, resolve } from 'pathe'
import type { Task } from '@vitest/runner'
import type { ErrorWithDiff } from '@vitest/utils'
import { getSuites } from '@vitest/runner/utils'
import type { Vitest } from '../../node'
import type { Reporter } from '../../types/reporter'
import { parseErrorStacktrace } from '../../utils/source-map'
@ -219,6 +220,15 @@ export class JUnitReporter implements Reporter {
skipped: 0,
})
// inject failed suites to surface errors during beforeAll/afterAll
const suites = getSuites(file)
for (const suite of suites) {
if (suite.result?.errors) {
tasks.push(suite)
stats.failures += 1
}
}
// If there are no tests, but the file failed to load, we still want to report it as a failure
if (tasks.length === 0 && file.result?.state === 'fail') {
stats.failures = 1

View File

@ -0,0 +1,26 @@
import {
afterAll,
beforeAll,
describe,
it,
} from 'vitest';
describe('suite with beforeAll', () => {
beforeAll(() => {
throw new Error('beforeAll error');
});
it('ok 1', () => {});
it('ok 2', () => {});
it.skip('skip 1', () => {});
});
describe('suite with afterAll', () => {
afterAll(() => {
throw new Error('afterAll error');
});
it('ok 1', () => {});
it('ok 2', () => {});
it.skip('skip 1', () => {});
});

View File

@ -0,0 +1,3 @@
import { defineConfig } from 'vitest/config'
export default defineConfig({})

View File

@ -0,0 +1,36 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`emits <failure> when beforeAll/afterAll failed 1`] = `
"<?xml version="1.0" encoding="UTF-8" ?>
<testsuites name="vitest tests" tests="8" failures="2" errors="0" time="...">
<testsuite name="basic.test.ts" timestamp="..." hostname="..." tests="8" failures="2" errors="0" skipped="2" time="...">
<testcase classname="basic.test.ts" name="suite with beforeAll &gt; ok 1" time="...">
</testcase>
<testcase classname="basic.test.ts" name="suite with beforeAll &gt; ok 2" time="...">
</testcase>
<testcase classname="basic.test.ts" name="suite with beforeAll &gt; skip 1" time="...">
<skipped/>
</testcase>
<testcase classname="basic.test.ts" name="suite with afterAll &gt; ok 1" time="...">
</testcase>
<testcase classname="basic.test.ts" name="suite with afterAll &gt; ok 2" time="...">
</testcase>
<testcase classname="basic.test.ts" name="suite with afterAll &gt; skip 1" time="...">
<skipped/>
</testcase>
<testcase classname="basic.test.ts" name="suite with beforeAll" time="...">
<failure message="beforeAll error" type="Error">
Error: beforeAll error
basic.test.ts:10:11
</failure>
</testcase>
<testcase classname="basic.test.ts" name="suite with afterAll" time="...">
<failure message="afterAll error" type="Error">
Error: afterAll error
basic.test.ts:20:11
</failure>
</testcase>
</testsuite>
</testsuites>
"
`;

View File

@ -52,3 +52,10 @@ test('emits <failure> if a test has a syntax error', async () => {
expect(xml).toContain('<testsuite name="with-syntax-error.test.js" timestamp="TIMESTAMP" hostname="HOSTNAME" tests="1" failures="1" errors="0" skipped="0" time="0">')
expect(xml).toContain('<failure')
})
test('emits <failure> when beforeAll/afterAll failed', async () => {
let { stdout } = await runVitest({ reporters: 'junit', root: './fixtures/suite-hook-failure' })
// reduct non-deterministic output
stdout = stdout.replaceAll(/(timestamp|hostname|time)=".*?"/g, '$1="..."')
expect(stdout).toMatchSnapshot()
})