diff --git a/docs/advanced/reporters.md b/docs/advanced/reporters.md index 84d31ca13eef..faa34090ba68 100644 --- a/docs/advanced/reporters.md +++ b/docs/advanced/reporters.md @@ -196,6 +196,10 @@ export interface TestResultSkipped { } export interface TestDiagnostic { + /** + * If the duration of the test is above `slowTestThreshold`. + */ + slow: boolean /** * The amount of memory used by the test in bytes. * This value is only available if the test was executed with `logHeapUsage` flag. diff --git a/docs/config/index.md b/docs/config/index.md index f52e246a5f0c..f9321433d458 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -2174,7 +2174,7 @@ Path to custom tsconfig, relative to the project root. - **Default**: `300` - **CLI**: `--slow-test-threshold=`, `--slowTestThreshold=` -The number of milliseconds after which a test is considered slow and reported as such in the results. +The number of milliseconds after which a test or suite is considered slow and reported as such in the results. ### chaiConfig {#chaiconfig} diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts index 05b83a555a17..841d49b19000 100644 --- a/packages/vitest/src/node/cli/cli-config.ts +++ b/packages/vitest/src/node/cli/cli-config.ts @@ -656,7 +656,7 @@ export const cliOptionsConfig: VitestCLIOptions = { }, slowTestThreshold: { description: - 'Threshold in milliseconds for a test to be considered slow (default: `300`)', + 'Threshold in milliseconds for a test or suite to be considered slow (default: `300`)', argument: '', }, teardownTimeout: { diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index d355b966e8d4..9892fa86e73d 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -10,7 +10,7 @@ import type { Vitest } from '../core' import type { Reporter } from '../types/reporter' import type { ErrorWithDiff, UserConsoleLog } from '../../types/general' import { hasFailedSnapshot } from '../../utils/tasks' -import { F_POINTER, F_RIGHT } from './renderers/figures' +import { F_CHECK, F_POINTER, F_RIGHT } from './renderers/figures' import { countTestErrors, divider, @@ -131,13 +131,7 @@ export abstract class BaseReporter implements Reporter { state += ` ${c.dim('|')} ${c.yellow(`${skipped.length} skipped`)}` } let suffix = c.dim(' (') + state + c.dim(')') - if (task.result.duration) { - const color - = task.result.duration > this.ctx.config.slowTestThreshold - ? c.yellow - : c.gray - suffix += color(` ${Math.round(task.result.duration)}${c.dim('ms')}`) - } + suffix += this.getDurationPrefix(task) if (this.ctx.config.logHeapUsage && task.result.heap != null) { suffix += c.magenta( ` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`, @@ -154,13 +148,36 @@ export abstract class BaseReporter implements Reporter { title += `${task.name} ${suffix}` logger.log(title) - // print short errors, full errors will be at the end in summary - for (const test of failed) { - logger.log(c.red(` ${taskFail} ${getTestName(test, c.dim(' > '))}`)) - test.result?.errors?.forEach((e) => { - logger.log(c.red(` ${F_RIGHT} ${(e as any)?.message}`)) - }) + for (const test of tests) { + const duration = test.result?.duration + if (test.result?.state === 'fail') { + const suffix = this.getDurationPrefix(test) + logger.log(c.red(` ${taskFail} ${getTestName(test, c.dim(' > '))}${suffix}`)) + + test.result?.errors?.forEach((e) => { + // print short errors, full errors will be at the end in summary + logger.log(c.red(` ${F_RIGHT} ${(e as any)?.message}`)) + }) + } + // also print slow tests + else if (duration && duration > this.ctx.config.slowTestThreshold) { + logger.log( + ` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(' > '))}${c.yellow( + ` ${Math.round(duration)}${c.dim('ms')}`, + )}`, + ) + } + } + } + + private getDurationPrefix(task: Task) { + if (!task.result?.duration) { + return '' } + const color = task.result.duration > this.ctx.config.slowTestThreshold + ? c.yellow + : c.gray + return color(` ${Math.round(task.result.duration)}${c.dim('ms')}`) } onWatcherStart( diff --git a/packages/vitest/src/node/reporters/reported-tasks.ts b/packages/vitest/src/node/reporters/reported-tasks.ts index 6914e2cf6165..aa0964bf6c32 100644 --- a/packages/vitest/src/node/reporters/reported-tasks.ts +++ b/packages/vitest/src/node/reporters/reported-tasks.ts @@ -155,9 +155,12 @@ export class TestCase extends ReportedTaskImplementation { if (!result || result.state === 'run' || !result.startTime) { return undefined } + const duration = result.duration || 0 + const slow = duration > this.project.globalConfig.slowTestThreshold return { + slow, heap: result.heap, - duration: result.duration!, + duration, startTime: result.startTime, retryCount: result.retryCount ?? 0, repeatCount: result.repeatCount ?? 0, @@ -441,6 +444,10 @@ export interface TestResultSkipped { } export interface TestDiagnostic { + /** + * If the duration of the test is above `slowTestThreshold`. + */ + slow: boolean /** * The amount of memory used by the test in bytes. * This value is only available if the test was executed with `logHeapUsage` flag. diff --git a/test/reporters/tests/merge-reports.test.ts b/test/reporters/tests/merge-reports.test.ts index b66ccd7c7c9d..1ca7cc3cadf2 100644 --- a/test/reporters/tests/merge-reports.test.ts +++ b/test/reporters/tests/merge-reports.test.ts @@ -89,13 +89,13 @@ test('merge reports', async () => { test 1-2 ❯ first.test.ts (2 tests | 1 failed)