Skip to content

Commit 1988fcb

Browse files
AriPerkkiosheremet-va
andauthoredMay 29, 2023
feat(coverage): add reportOnFailure option (#3453)
Co-authored-by: Vladimir <sleuths.slews0s@icloud.com>
1 parent b664d42 commit 1988fcb

File tree

9 files changed

+83
-32
lines changed

9 files changed

+83
-32
lines changed
 

‎docs/config/index.md

+10
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,16 @@ The reporter has three different types:
778778

779779
Since Vitest 0.31.0, you can check your coverage report in Vitest UI: check [Vitest UI Coverage](/guide/coverage#vitest-ui) for more details.
780780

781+
#### coverage.reportOnFailure
782+
783+
- **Type:** `boolean`
784+
- **Default:** `true`
785+
- **Available for providers:** `'c8' | 'istanbul'`
786+
- **CLI:** `--coverage.reportOnFailure`, `--coverage.reportOnFailure=false`
787+
- **Version:** Since Vitest 0.31.2
788+
789+
Generate coverage report even when tests fail.
790+
781791
#### coverage.skipFull
782792

783793
- **Type:** `boolean`

‎packages/vitest/src/defaults.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const coverageConfigDefaults: ResolvedCoverageOptions = {
3333
cleanOnRerun: true,
3434
reportsDirectory: './coverage',
3535
exclude: defaultCoverageExcludes,
36+
reportOnFailure: true,
3637
reporter: [['text', {}], ['html', {}], ['clover', {}], ['json', {}]],
3738
// default extensions used by c8, plus '.vue' and '.svelte'
3839
// see https://github.com/istanbuljs/schema/blob/master/default-extension.js

‎packages/vitest/src/node/core.ts

+3
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,9 @@ export class Vitest {
692692
}
693693

694694
private async reportCoverage(allTestsRun: boolean) {
695+
if (!this.config.coverage.reportOnFailure && this.state.getCountOfFailedTests() > 0)
696+
return
697+
695698
if (this.coverageProvider) {
696699
this.logger.log(c.blue(' % ') + c.dim('Coverage report from ') + c.yellow(this.coverageProvider.name))
697700
await this.coverageProvider.reportCoverage({ allTestsRun })

‎packages/vitest/src/types/coverage.ts

+8
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type FieldsWithDefaultValues =
7777
| 'reportsDirectory'
7878
| 'exclude'
7979
| 'extension'
80+
| 'reportOnFailure'
8081

8182
export type ResolvedCoverageOptions<T extends Provider = Provider> =
8283
& CoverageOptions<T>
@@ -208,6 +209,13 @@ export interface BaseCoverageOptions {
208209
* @default false
209210
*/
210211
thresholdAutoUpdate?: boolean
212+
213+
/**
214+
* Generate coverage report even when tests fail.
215+
*
216+
* @default true
217+
*/
218+
reportOnFailure?: boolean
211219
}
212220

213221
export interface CoverageIstanbulOptions extends BaseCoverageOptions {

‎pnpm-lock.yaml

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/coverage-test/test/configuration-options.test-d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ test('provider module', () => {
105105
extension: ['string'],
106106
reporter: [['html', {}], ['json', { file: 'string' }]],
107107
reportsDirectory: 'string',
108+
reportOnFailure: true,
108109
}
109110
},
110111
clean(_: boolean) {},

‎test/fails/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"coverage": "vitest run --coverage"
77
},
88
"devDependencies": {
9+
"@vitest/coverage-istanbul": "workspace:*",
910
"jsdom": "^21.0.0",
1011
"vitest": "workspace:*"
1112
}
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`should fails > .dot-folder/dot-test.test.ts > .dot-folder/dot-test.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`;
3+
exports[`should fail .dot-folder/dot-test.test.ts > .dot-folder/dot-test.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`;
44

5-
exports[`should fails > each-timeout.test.ts > each-timeout.test.ts 1`] = `"Error: Test timed out in 10ms."`;
5+
exports[`should fail each-timeout.test.ts > each-timeout.test.ts 1`] = `"Error: Test timed out in 10ms."`;
66

7-
exports[`should fails > empty.test.ts > empty.test.ts 1`] = `"Error: No test suite found in file <rootDir>/empty.test.ts"`;
7+
exports[`should fail empty.test.ts > empty.test.ts 1`] = `"Error: No test suite found in file <rootDir>/empty.test.ts"`;
88
9-
exports[`should fails > expect.test.ts > expect.test.ts 1`] = `"AssertionError: expected 2 to deeply equal 3"`;
9+
exports[`should fail expect.test.ts > expect.test.ts 1`] = `"AssertionError: expected 2 to deeply equal 3"`;
1010
11-
exports[`should fails > hook-timeout.test.ts > hook-timeout.test.ts 1`] = `"Error: Hook timed out in 10ms."`;
11+
exports[`should fail hook-timeout.test.ts > hook-timeout.test.ts 1`] = `"Error: Hook timed out in 10ms."`;
1212
13-
exports[`should fails > hooks-called.test.ts > hooks-called.test.ts 1`] = `
13+
exports[`should fail hooks-called.test.ts > hooks-called.test.ts 1`] = `
1414
"Error: after all
1515
Error: before all"
1616
`;
1717
18-
exports[`should fails > inline-snapshop-inside-each.test.ts > inline-snapshop-inside-each.test.ts 1`] = `
18+
exports[`should fail inline-snapshop-inside-each.test.ts > inline-snapshop-inside-each.test.ts 1`] = `
1919
"Error: InlineSnapshot cannot be used inside of test.each or describe.each
2020
Error: InlineSnapshot cannot be used inside of test.each or describe.each
2121
Error: InlineSnapshot cannot be used inside of test.each or describe.each
2222
Error: InlineSnapshot cannot be used inside of test.each or describe.each
2323
Error: InlineSnapshot cannot be used inside of test.each or describe.each"
2424
`;
2525
26-
exports[`should fails > mock-import-proxy-module.test.ts > mock-import-proxy-module.test.ts 1`] = `"Error: There are some problems in resolving the mocks API."`;
26+
exports[`should fail mock-import-proxy-module.test.ts > mock-import-proxy-module.test.ts 1`] = `"Error: There are some problems in resolving the mocks API."`;
2727
28-
exports[`should fails > nested-suite.test.ts > nested-suite.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`;
28+
exports[`should fail nested-suite.test.ts > nested-suite.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`;
2929
30-
exports[`should fails > primitive-error.test.ts > primitive-error.test.ts 1`] = `"Unknown Error: 42"`;
30+
exports[`should fail primitive-error.test.ts > primitive-error.test.ts 1`] = `"Unknown Error: 42"`;
3131
32-
exports[`should fails > stall.test.ts > stall.test.ts 1`] = `
32+
exports[`should fail stall.test.ts > stall.test.ts 1`] = `
3333
"TypeError: failure
3434
TypeError: failure
3535
TypeError: failure
3636
TypeError: failure"
3737
`;
3838
39-
exports[`should fails > test-timeout.test.ts > test-timeout.test.ts 1`] = `"Error: Test timed out in 10ms."`;
39+
exports[`should fail test-timeout.test.ts > test-timeout.test.ts 1`] = `"Error: Test timed out in 10ms."`;
4040
41-
exports[`should fails > unhandled.test.ts > unhandled.test.ts 1`] = `
41+
exports[`should fail unhandled.test.ts > unhandled.test.ts 1`] = `
4242
"Error: some error
4343
Error: Uncaught [Error: some error]"
4444
`;

‎test/fails/test/runner.test.ts

+43-19
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,49 @@
11
import { resolve } from 'pathe'
22
import fg from 'fast-glob'
3-
import { describe, expect, it } from 'vitest'
3+
import { expect, it } from 'vitest'
44

55
import { runVitest } from '../../test-utils'
66

7-
describe('should fails', async () => {
8-
const root = resolve(__dirname, '../fixtures')
9-
const files = await fg('**/*.test.ts', { cwd: root, dot: true })
10-
11-
for (const file of files) {
12-
it(file, async () => {
13-
const { stderr } = await runVitest({ root }, [file])
14-
15-
expect(stderr).toBeTruthy()
16-
const msg = String(stderr)
17-
.split(/\n/g)
18-
.reverse()
19-
.filter(i => i.includes('Error: ') && !i.includes('Command failed') && !i.includes('stackStr') && !i.includes('at runTest'))
20-
.map(i => i.trim().replace(root, '<rootDir>'),
21-
).join('\n')
22-
expect(msg).toMatchSnapshot(file)
23-
}, 30_000)
24-
}
7+
const root = resolve(__dirname, '../fixtures')
8+
const files = await fg('**/*.test.ts', { cwd: root, dot: true })
9+
10+
it.each(files)('should fail %s', async (file) => {
11+
const { stderr } = await runVitest({ root }, [file])
12+
13+
expect(stderr).toBeTruthy()
14+
const msg = String(stderr)
15+
.split(/\n/g)
16+
.reverse()
17+
.filter(i => i.includes('Error: ') && !i.includes('Command failed') && !i.includes('stackStr') && !i.includes('at runTest'))
18+
.map(i => i.trim().replace(root, '<rootDir>'),
19+
).join('\n')
20+
expect(msg).toMatchSnapshot(file)
21+
}, 30_000)
22+
23+
it('should report coverage when "coverag.reportOnFailure: true" and tests fail', async () => {
24+
const { stdout } = await runVitest({
25+
root,
26+
coverage: {
27+
enabled: true,
28+
provider: 'istanbul',
29+
reportOnFailure: true,
30+
reporter: ['text'],
31+
},
32+
}, [files[0]])
33+
34+
expect(stdout).toMatch('Coverage report from istanbul')
35+
})
36+
37+
it('should not report coverage when "coverag.reportOnFailure: false" and tests fail', async () => {
38+
const { stdout } = await runVitest({
39+
root,
40+
coverage: {
41+
enabled: true,
42+
provider: 'istanbul',
43+
reportOnFailure: false,
44+
reporter: ['text'],
45+
},
46+
}, [files[0]])
47+
48+
expect(stdout).not.toMatch('Coverage report from istanbul')
2549
})

0 commit comments

Comments
 (0)
Please sign in to comment.