Skip to content

Commit

Permalink
feat: add config option logHeapUsage (#1225)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed May 3, 2022
1 parent 6572255 commit 9c42c4f
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 3 deletions.
7 changes: 7 additions & 0 deletions docs/config/index.md
Expand Up @@ -448,3 +448,10 @@ export default {
},
}
```

### logHeapUsage

- **Type**: `boolean`
- **Default**: `false`

Show heap usage after each test. Usefull for debugging memory leaks.
10 changes: 8 additions & 2 deletions packages/vitest/src/node/reporters/base.ts
Expand Up @@ -16,6 +16,8 @@ const HELP_QUITE = `${c.dim('press ')}${c.bold('q')}${c.dim(' to quit')}`
const WAIT_FOR_CHANGE_PASS = `\n${c.bold(c.inverse(c.green(' PASS ')))}${c.green(' Waiting for file changes...')}`
const WAIT_FOR_CHANGE_FAIL = `\n${c.bold(c.inverse(c.red(' FAIL ')))}${c.red(' Tests failed. Watching for file changes...')}`

const DURATION_LONG = 300

export abstract class BaseReporter implements Reporter {
start = 0
end = 0
Expand Down Expand Up @@ -86,8 +88,12 @@ export abstract class BaseReporter implements Reporter {
if (skipped.length)
state += ` ${c.dim('|')} ${c.yellow(`${skipped.length} skipped`)}`
let suffix = c.dim(' (') + state + c.dim(')')
if (task.result.duration)
suffix += c.yellow(` ${Math.round(task.result.duration)}${c.dim('ms')}`)
if (task.result.duration) {
const color = task.result.duration > DURATION_LONG ? c.yellow : c.gray
suffix += color(` ${Math.round(task.result.duration)}${c.dim('ms')}`)
}
if (this.ctx.config.logHeapUsage && task.result.heap != null)
suffix += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`)

this.ctx.log(` ${getStateSymbol(task)} ${task.name} ${suffix}`)

Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/node/reporters/default.ts
Expand Up @@ -22,6 +22,7 @@ export class DefaultReporter extends BaseReporter {
onCollected() {
if (this.isTTY) {
this.rendererOptions.outputStream = this.ctx.outputStream
this.rendererOptions.showHeap = this.ctx.config.logHeapUsage
const files = this.ctx.state.getFiles(this.watchFilters)
if (!this.renderer)
this.renderer = createListRenderer(files, this.rendererOptions).start()
Expand Down
4 changes: 4 additions & 0 deletions packages/vitest/src/node/reporters/renderers/listRenderer.ts
Expand Up @@ -10,6 +10,7 @@ import { getCols, getHookStateSymbol, getStateSymbol } from './utils'
export interface ListRendererOptions {
renderSucceed?: boolean
outputStream: NodeJS.WritableStream
showHeap: boolean
}

const DURATION_LONG = 300
Expand Down Expand Up @@ -53,6 +54,9 @@ export function renderTree(tasks: Task[], options: ListRendererOptions, level =
suffix += c.yellow(` ${Math.round(task.result.duration)}${c.dim('ms')}`)
}

if (options.showHeap && task.result?.heap != null)
suffix += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`)

let name = task.name
if (level === 0)
name = formatFilepath(name)
Expand Down
5 changes: 4 additions & 1 deletion packages/vitest/src/node/reporters/verbose.ts
Expand Up @@ -17,7 +17,10 @@ export class VerboseReporter extends DefaultReporter {
for (const pack of packs) {
const task = this.ctx.state.idMap.get(pack[0])
if (task && task.type === 'test' && task.result?.state && task.result?.state !== 'run') {
this.ctx.log(` ${getStateSymbol(task)} ${getFullName(task)}`)
let title = ` ${getStateSymbol(task)} ${getFullName(task)}`
if (this.ctx.config.logHeapUsage && task.result.heap != null)
title += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`)
this.ctx.log(title)
if (task.result.state === 'fail')
this.ctx.log(c.red(` ${F_RIGHT} ${(task.result.error as any)?.message}`))
}
Expand Down
8 changes: 8 additions & 0 deletions packages/vitest/src/runtime/run.ts
Expand Up @@ -151,6 +151,9 @@ export async function runTest(test: Test) {

test.result.duration = now() - start

if (workerState.config.logHeapUsage)
test.result.heap = process.memoryUsage().heapUsed

workerState.current = undefined

updateTask(test)
Expand Down Expand Up @@ -212,6 +215,11 @@ export async function runSuite(suite: Suite) {
}
suite.result.duration = now() - start

const workerState = getWorkerState()

if (workerState.config.logHeapUsage)
suite.result.heap = process.memoryUsage().heapUsed

if (suite.mode === 'run') {
if (!hasTests(suite)) {
suite.result.state = 'fail'
Expand Down
5 changes: 5 additions & 0 deletions packages/vitest/src/types/config.ts
Expand Up @@ -297,6 +297,11 @@ export interface InlineConfig {
* Resolve custom snapshot path
*/
resolveSnapshotPath?: (path: string, extension: string) => string

/**
* Show heap usage after each test. Usefull for debugging memory leaks.
*/
logHeapUsage?: boolean
}

export interface UserConfig extends InlineConfig {
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/types/tasks.ts
Expand Up @@ -20,6 +20,7 @@ export interface TaskResult {
state: TaskState
duration?: number
startTime?: number
heap?: number
error?: ErrorWithDiff
htmlError?: string
hooks?: Partial<Record<keyof SuiteHooks, TaskState>>
Expand Down

0 comments on commit 9c42c4f

Please sign in to comment.