Skip to content

Commit a233685

Browse files
authored
feat(experimental): print how many tests were affected and a total when running --changed (#11424)
1 parent c74e099 commit a233685

4 files changed

Lines changed: 77 additions & 2 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export class Vitest {
151151

152152
/** @internal */ configOverride: Partial<ResolvedConfig> = {}
153153
/** @internal */ filenamePattern?: string[]
154+
/** @internal */ _sourceFilterResult?: { affected: number; total: number }
154155
/** @internal */ runningPromise?: Promise<TestRunResult>
155156
/** @internal */ closingPromise?: Promise<void>
156157
/** @internal */ cancelPromise?: Promise<void | void[]>
@@ -1102,6 +1103,7 @@ export class Vitest {
11021103
// all subsequent runs will treat this as a fresh run
11031104
this.config.changed = false
11041105
this.config.related = undefined
1106+
this._sourceFilterResult = undefined
11051107
})
11061108

11071109
return await this.runningPromise
@@ -1301,6 +1303,7 @@ export class Vitest {
13011303
// all subsequent runs will treat this as a fresh run
13021304
this.config.changed = false
13031305
this.config.related = undefined
1306+
this._sourceFilterResult = undefined
13041307
})
13051308

13061309
return await this.runningPromise

‎packages/vitest/src/node/reporters/base.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import {
5454
formatTimeString,
5555
getStateString,
5656
getStateSymbol,
57+
noun,
5758
padSummaryTitle,
5859
renderSnapshotSummary,
5960
separator,
@@ -659,6 +660,25 @@ export abstract class BaseReporter implements Reporter {
659660
this.reportTestSummary(files, errors, leakCount)
660661
}
661662

663+
private printSourceFilterSummary(): void {
664+
const result = this.ctx._sourceFilterResult
665+
const related = this.ctx.config.related
666+
if (!result || !related) {
667+
return
668+
}
669+
670+
const sources =
671+
related.length === 1 && !this.ctx.config.changed
672+
? relative(this.ctx.config.root, related[0])
673+
: `${related.length} ${this.ctx.config.changed ? 'changed ' : ''}${noun(related.length, 'file', 'files')}`
674+
675+
this.log(
676+
padSummaryTitle('Affected'),
677+
`${result.affected} of ${result.total} test files`,
678+
c.dim(`(related to ${sources})`),
679+
)
680+
}
681+
662682
reportTestSummary(files: File[], errors: unknown[], leakCount: number): void {
663683
this.log()
664684

@@ -677,6 +697,7 @@ export abstract class BaseReporter implements Reporter {
677697
}
678698

679699
this.log(padSummaryTitle('Test Files'), getStateString(affectedFiles))
700+
this.printSourceFilterSummary()
680701
this.log(padSummaryTitle('Tests'), getStateString(tests))
681702

682703
if (this.ctx.projects.some((c) => c.config.typecheck.enabled)) {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ export class VitestSpecifications {
117117
}
118118

119119
private async filterTestsBySource(specs: TestSpecification[]): Promise<TestSpecification[]> {
120+
this.vitest._sourceFilterResult = undefined
121+
120122
if (this.vitest.config.changed && !this.vitest.config.related) {
121123
const related = await this.vitest.vcs.findChangedFiles({
122124
root: this.vitest.config.root,
@@ -157,7 +159,11 @@ export class VitestSpecifications {
157159
affectedByProject.set(project, await this.getAffectedModules(project, projectSpecs, related))
158160
}
159161

160-
return specs.filter((spec) => affectedByProject.get(spec.project)!.has(spec.moduleId))
162+
const affectedSpecs = specs.filter((spec) =>
163+
affectedByProject.get(spec.project)!.has(spec.moduleId),
164+
)
165+
this.vitest._sourceFilterResult = { affected: affectedSpecs.length, total: specs.length }
166+
return affectedSpecs
161167
}
162168

163169
/**

‎test/e2e/test/vcs-provider.test.ts‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ import { expect, onTestFinished, test, vi } from 'vitest'
44
import { createVitest } from 'vitest/node'
55
import { runInlineTests, useFS } from '#test-utils'
66

7+
function affectedSummary(stdout: string) {
8+
return stdout.split('\n').find((line) => line.includes('Affected'))
9+
}
10+
711
test('custom vcsProvider that returns specific files runs only matching tests', async () => {
8-
const { testTree, stderr } = await runInlineTests(
12+
const { testTree, stderr, stdout } = await runInlineTests(
913
{
1014
'vitest.config.js': `
1115
import path from 'node:path'
@@ -51,6 +55,47 @@ test('custom vcsProvider that returns specific files runs only matching tests',
5155
},
5256
}
5357
`)
58+
expect(affectedSummary(stdout)).toMatchInlineSnapshot(
59+
`" Affected 1 of 2 test files (related to 1 changed file)"`,
60+
)
61+
})
62+
63+
test('related prints how many test files were affected', async () => {
64+
const { testTree, stderr, stdout } = await runInlineTests(
65+
{
66+
'src/changed.ts': 'export const a = 1',
67+
'src/not-changed.ts': 'export const b = 2',
68+
'related.test.ts': `
69+
import { a } from './src/changed.ts'
70+
import { test, expect } from 'vitest'
71+
test('related test', () => {
72+
expect(a).toBe(1)
73+
})
74+
`,
75+
'not-related.test.ts': `
76+
import { b } from './src/not-changed.ts'
77+
import { test, expect } from 'vitest'
78+
test('not related test', () => {
79+
expect(b).toBe(2)
80+
})
81+
`,
82+
},
83+
{
84+
related: ['src/changed.ts'],
85+
},
86+
)
87+
88+
expect(stderr).toBe('')
89+
expect(testTree()).toMatchInlineSnapshot(`
90+
{
91+
"related.test.ts": {
92+
"related test": "passed",
93+
},
94+
}
95+
`)
96+
expect(affectedSummary(stdout)).toMatchInlineSnapshot(
97+
`" Affected 1 of 2 test files (related to src/changed.ts)"`,
98+
)
5499
})
55100

56101
test('custom vcsProvider that returns no files runs no tests', async () => {

0 commit comments

Comments
 (0)