Skip to content

Commit

Permalink
feat: verbose reporter to show slow in-progress tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio committed Nov 12, 2024
1 parent 9f5803e commit 77e34b2
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 10 deletions.
20 changes: 19 additions & 1 deletion docs/guide/reporters.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Example output using basic reporter:

### Verbose Reporter

Verbose reporter is same as `default` reporter, but it also displays each individual test after the suite has finished. Similar to `default` reporter, you can disable the summary by configuring the reporter.
Verbose reporter is same as `default` reporter, but it also displays each individual test after the suite has finished. It also displays currently running tests that are taking longer than [`slowTestThreshold`](/config/#slowtestthreshold). Similar to `default` reporter, you can disable the summary by configuring the reporter.

:::code-group
```bash [CLI]
Expand All @@ -190,6 +190,24 @@ export default defineConfig({
```
:::

Example output for tests in progress with default `slowTestThreshold: 300`:

```bash
✓ __tests__/example-1.test.ts (2) 725ms
✓ first test file (2) 725ms
✓ 2 + 2 should equal 4
✓ 4 - 2 should equal 2

❯ test/example-2.test.ts 3/5
↳ should run longer than three seconds 1.57s
❯ test/example-3.test.ts 1/5

Test Files 2 passed (4)
Tests 10 passed | 3 skipped (65)
Start at 11:01:36
Duration 2.00s
```

Example of final terminal output for a passing test suite:

```bash
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/reporters/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class DefaultReporter extends BaseReporter {

onInit(ctx: Vitest) {
super.onInit(ctx)
this.summary?.onInit(ctx)
this.summary?.onInit(ctx, { verbose: this.verbose })
}

onPathsCollected(paths: string[] = []) {
Expand Down
2 changes: 2 additions & 0 deletions packages/vitest/src/node/reporters/renderers/figures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export const F_CHECK = '✓'
export const F_CROSS = '×'
export const F_LONG_DASH = '⎯'
export const F_RIGHT_TRI = '▶'
export const F_TREE_NODE_MIDDLE = '├──'
export const F_TREE_NODE_END = '└──'
93 changes: 85 additions & 8 deletions packages/vitest/src/node/reporters/summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import type { Vitest } from '../core'
import type { Reporter } from '../types/reporter'
import { getTests } from '@vitest/runner/utils'
import c from 'tinyrainbow'
import { F_POINTER } from './renderers/figures'
import { F_POINTER, F_TREE_NODE_END, F_TREE_NODE_MIDDLE } from './renderers/figures'
import { formatProjectName, formatTime, formatTimeString, padSummaryTitle } from './renderers/utils'
import { WindowRenderer } from './renderers/windowedRenderer'

const DURATION_UPDATE_INTERVAL_MS = 500
const DURATION_UPDATE_INTERVAL_MS = 100
const FINISHED_TEST_CLEANUP_TIME_MS = 1_000

interface Options {
verbose?: boolean
}

interface Counter {
total: number
completed: number
Expand All @@ -19,9 +23,17 @@ interface Counter {
todo: number
}

interface SlowTest {
name?: string
startTime: number
timeout: NodeJS.Timeout

}

interface RunningTest extends Pick<Counter, 'total' | 'completed'> {
filename: File['name']
projectName: File['projectName']
slowTests: Map<Test['id'], SlowTest>
}

/**
Expand All @@ -30,6 +42,7 @@ interface RunningTest extends Pick<Counter, 'total' | 'completed'> {
*/
export class SummaryReporter implements Reporter {
private ctx!: Vitest
private options!: Options
private renderer!: WindowRenderer

private suites = emptyCounters()
Expand All @@ -46,12 +59,18 @@ export class SummaryReporter implements Reporter {
private allFinishedTests = new Set<File['id']>()

private startTime = ''
private currentTime = 0
private duration = 0
private durationInterval: NodeJS.Timeout | undefined = undefined

onInit(ctx: Vitest) {
onInit(ctx: Vitest, options: Options = {}) {
this.ctx = ctx

this.options = {
verbose: false,
...options,
}

this.renderer = new WindowRenderer({
logger: ctx.logger,
getWindow: () => this.createSummary(),
Expand Down Expand Up @@ -88,7 +107,10 @@ export class SummaryReporter implements Reporter {
}

if (task?.type === 'test' || task?.type === 'custom') {
if (task.result?.state !== 'run') {
if (task.result?.state === 'run') {
this.onTestStart(task)
}
else {
this.onTestFinished(task)
}
}
Expand Down Expand Up @@ -127,9 +149,12 @@ export class SummaryReporter implements Reporter {
const finished = this.finishedTests.entries().next().value

if (finished) {
const slowTests = this.runningTests.get(finished[0])?.slowTests
slowTests?.forEach(slowTest => clearTimeout(slowTest.timeout))

clearTimeout(finished[1])
this.finishedTests.delete(finished[0])
this.runningTests.delete(finished[0])
this.finishedTests.delete(finished[0])
}
}

Expand All @@ -138,12 +163,13 @@ export class SummaryReporter implements Reporter {
completed: 0,
filename: file.name,
projectName: file.projectName,
slowTests: new Map(),
})

this.maxParallelTests = Math.max(this.maxParallelTests, this.runningTests.size)
}

private onTestFinished(test: Test | Custom) {
private getTestStats(test: Test | Custom) {
const file = test.file
let stats = this.runningTests.get(file.id)

Expand All @@ -158,6 +184,43 @@ export class SummaryReporter implements Reporter {
}
}

return stats
}

private onTestStart(test: Test | Custom) {
// Track slow running tests only on verbose mode
if (!this.options.verbose) {
return
}

const stats = this.getTestStats(test)

if (!stats) {
return
}

const slowTest: SlowTest = {
name: undefined,
startTime: performance.now(),
timeout: setTimeout(() => {
slowTest.name = test.name
}, this.ctx.config.slowTestThreshold).unref(),
}

stats.slowTests.set(test.id, slowTest)
}

private onTestFinished(test: Test | Custom) {
const file = test.file
const stats = this.getTestStats(test)

if (!stats) {
return
}

clearTimeout(stats.slowTests.get(test.id)?.timeout)
stats.slowTests.delete(test.id)

stats.completed++
const result = test.result

Expand Down Expand Up @@ -225,6 +288,19 @@ export class SummaryReporter implements Reporter {
+ test.filename
+ c.dim(` ${test.completed}/${test.total}`),
)

const slowTests = Array.from(test.slowTests.values()).filter(t => t.name)

for (const [index, slowTest] of slowTests.entries()) {
const elapsed = this.currentTime - slowTest.startTime
const icon = index === slowTests.length - 1 ? F_TREE_NODE_END : F_TREE_NODE_MIDDLE

summary.push(
c.bold(c.yellow(` ${icon} `))
+ slowTest.name
+ c.bold(c.yellow(` ${formatTime(Math.max(0, elapsed))}`)),
)
}
}

if (this.runningTests.size > 0) {
Expand All @@ -246,8 +322,9 @@ export class SummaryReporter implements Reporter {
this.startTime = formatTimeString(new Date())

this.durationInterval = setInterval(() => {
this.duration = performance.now() - start
}, DURATION_UPDATE_INTERVAL_MS)
this.currentTime = performance.now()
this.duration = this.currentTime - start
}, DURATION_UPDATE_INTERVAL_MS).unref()
}
}

Expand Down

0 comments on commit 77e34b2

Please sign in to comment.