Skip to content

Commit

Permalink
fix(vitest): show beforeAll/afterAll errors in junit reporter (#4819)
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa committed Dec 31, 2023
1 parent 7e6a62a commit 2baea35
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 0 deletions.
10 changes: 10 additions & 0 deletions packages/vitest/src/node/reporters/junit.ts
Expand Up @@ -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'
Expand Down Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions test/reporters/fixtures/suite-hook-failure/basic.test.ts
@@ -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', () => {});
});
3 changes: 3 additions & 0 deletions test/reporters/fixtures/suite-hook-failure/vitest.config.ts
@@ -0,0 +1,3 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({})
36 changes: 36 additions & 0 deletions test/reporters/tests/__snapshots__/junit.test.ts.snap
@@ -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>
"
`;
7 changes: 7 additions & 0 deletions test/reporters/tests/junit.test.ts
Expand Up @@ -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()
})

0 comments on commit 2baea35

Please sign in to comment.