or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdbenchmarking.mdbrowser-testing.mdconfiguration.mdindex.mdmocking.mdnode-apis.mdreporters.mdtest-definition.mdtimers.mdtype-testing.md

reporters.mddocs/

0

# Reporters

1

2

Vitest reporters format and output test results. Import from `vitest/reporters`.

3

4

## Built-in Reporters

5

6

11 built-in reporter classes are available:

7

8

### DefaultReporter

9

10

Default colored console output with test hierarchy.

11

12

```typescript { .api }

13

class DefaultReporter extends BaseReporter {

14

// Colored output with test results

15

// Shows: pass (✓), fail (✕), skip (-)

16

}

17

```

18

19

**Usage:**

20

21

```typescript

22

import { defineConfig } from 'vitest/config';

23

24

export default defineConfig({

25

test: {

26

reporters: ['default'] // or omit for default

27

}

28

});

29

```

30

31

### VerboseReporter

32

33

Extended test information with full output.

34

35

```typescript { .api }

36

class VerboseReporter extends BaseReporter {

37

// Detailed output including test names, durations, and full error stacks

38

}

39

```

40

41

**Usage:**

42

43

```typescript

44

export default defineConfig({

45

test: {

46

reporters: ['verbose']

47

}

48

});

49

```

50

51

### DotReporter

52

53

Minimal dot-based output.

54

55

```typescript { .api }

56

class DotReporter extends BaseReporter {

57

// Outputs: . (pass), x (fail), - (skip)

58

}

59

```

60

61

### TreeReporter

62

63

Tree-structured test hierarchy output.

64

65

```typescript { .api }

66

class TreeReporter extends BaseReporter {

67

// Tree view of test suites and tests

68

}

69

```

70

71

### JsonReporter

72

73

JSON-formatted test results.

74

75

```typescript { .api }

76

class JsonReporter extends BaseReporter {

77

// Outputs JSON test results to file

78

}

79

80

interface JsonTestResults {

81

numTotalTests: number;

82

numPassedTests: number;

83

numFailedTests: number;

84

numPendingTests: number;

85

testResults: JsonTestResult[];

86

}

87

88

interface JsonTestResult {

89

name: string;

90

status: 'passed' | 'failed' | 'skipped';

91

duration: number;

92

assertionResults: JsonAssertionResult[];

93

}

94

```

95

96

**Usage:**

97

98

```typescript

99

export default defineConfig({

100

test: {

101

reporters: ['json'],

102

outputFile: './test-results.json'

103

}

104

});

105

```

106

107

### JUnitReporter

108

109

JUnit XML format output.

110

111

```typescript { .api }

112

class JUnitReporter extends BaseReporter {

113

// Outputs JUnit XML format compatible with CI systems

114

}

115

```

116

117

**Usage:**

118

119

```typescript

120

export default defineConfig({

121

test: {

122

reporters: ['junit'],

123

outputFile: './junit.xml'

124

}

125

});

126

```

127

128

### TapReporter

129

130

TAP (Test Anything Protocol) format.

131

132

```typescript { .api }

133

class TapReporter extends BaseReporter {

134

// TAP format output

135

}

136

```

137

138

### TapFlatReporter

139

140

Flat TAP format output.

141

142

```typescript { .api }

143

class TapFlatReporter extends BaseReporter {

144

// Flattened TAP output

145

}

146

```

147

148

### GithubActionsReporter

149

150

GitHub Actions format for CI integration.

151

152

```typescript { .api }

153

class GithubActionsReporter extends BaseReporter {

154

// Formats errors for GitHub Actions annotations

155

}

156

```

157

158

**Usage:**

159

160

```typescript

161

export default defineConfig({

162

test: {

163

reporters: process.env.GITHUB_ACTIONS

164

? ['github-actions']

165

: ['default']

166

}

167

});

168

```

169

170

### HangingProcessReporter

171

172

Detects and reports hanging processes after tests complete.

173

174

```typescript { .api }

175

class HangingProcessReporter extends BaseReporter {

176

// Detects processes preventing test exit

177

}

178

```

179

180

### BlobReporter

181

182

Binary format for test results.

183

184

```typescript { .api }

185

class BlobReporter extends BaseReporter {

186

// Outputs binary blob format

187

}

188

```

189

190

## Custom Reporters

191

192

Create custom reporters by extending `BaseReporter`.

193

194

```typescript { .api }

195

abstract class BaseReporter {

196

/**

197

* Called when Vitest is initialized

198

*/

199

onInit(ctx: Vitest): void;

200

201

/**

202

* Called when test paths are collected

203

*/

204

onPathsCollected(paths?: string[]): void;

205

206

/**

207

* Called when tests are collected from files

208

*/

209

onCollected(files?: File[]): Promise<void> | void;

210

211

/**

212

* Called when all tests finish

213

*/

214

onFinished(

215

files?: File[],

216

errors?: unknown[]

217

): Promise<void> | void;

218

219

/**

220

* Called when a task updates

221

*/

222

onTaskUpdate(task: [string, TaskResult | undefined][]): void;

223

224

/**

225

* Called when a test is removed

226

*/

227

onTestRemoved(trigger?: string): void;

228

229

/**

230

* Called when watcher starts

231

*/

232

onWatcherStart(files?: File[], errors?: unknown[]): void;

233

234

/**

235

* Called when watcher reruns tests

236

*/

237

onWatcherRerun(files: string[], trigger?: string): void;

238

239

/**

240

* Called when server restarts

241

*/

242

onServerRestart(reason?: string): void;

243

244

/**

245

* Called when process times out

246

*/

247

onProcessTimeout(): void;

248

}

249

```

250

251

**Usage:**

252

253

```typescript

254

import { BaseReporter } from 'vitest/reporters';

255

import type { File, Vitest } from 'vitest';

256

257

class MyCustomReporter extends BaseReporter {

258

onInit(ctx: Vitest) {

259

console.log('Tests starting...');

260

}

261

262

onCollected(files?: File[]) {

263

console.log(`Collected ${files?.length} test files`);

264

}

265

266

onFinished(files?: File[], errors?: unknown[]) {

267

if (errors?.length) {

268

console.error(`Failed with ${errors.length} errors`);

269

} else {

270

console.log('All tests passed!');

271

}

272

}

273

}

274

275

export default defineConfig({

276

test: {

277

reporters: [new MyCustomReporter()]

278

}

279

});

280

```

281

282

## Multiple Reporters

283

284

Use multiple reporters simultaneously.

285

286

```typescript

287

export default defineConfig({

288

test: {

289

reporters: ['default', 'json', 'junit'],

290

outputFile: {

291

json: './results.json',

292

junit: './junit.xml'

293

}

294

}

295

});

296

```

297

298

## Reporter Registry

299

300

```typescript { .api }

301

/**

302

* Registry of built-in reporters

303

*/

304

const ReportersMap: Record<BuiltinReporters, typeof BaseReporter>;

305

306

type BuiltinReporters =

307

| 'default'

308

| 'verbose'

309

| 'dot'

310

| 'tree'

311

| 'json'

312

| 'blob'

313

| 'tap'

314

| 'tap-flat'

315

| 'junit'

316

| 'github-actions'

317

| 'hanging-process';

318

```

319

320

## Benchmark Reporters

321

322

Specialized reporters for benchmarking.

323

324

```typescript { .api }

325

class BenchmarkReporter {

326

onInit(ctx: Vitest): void;

327

onFinished(files?: File[], errors?: unknown[]): Promise<void> | void;

328

}

329

330

class VerboseBenchmarkReporter extends BenchmarkReporter {

331

// Detailed benchmark results with statistics

332

}

333

334

type BenchmarkBuiltinReporters = 'default' | 'verbose';

335

```

336

337

**Usage:**

338

339

```typescript

340

export default defineConfig({

341

test: {

342

benchmark: {

343

reporters: ['verbose']

344

}

345

}

346

});

347

```

348

349

## Common Patterns

350

351

### CI-Specific Reporters

352

353

```typescript

354

export default defineConfig({

355

test: {

356

reporters: process.env.CI

357

? ['junit', 'github-actions']

358

: ['default']

359

}

360

});

361

```

362

363

### Custom Metrics Reporter

364

365

```typescript

366

import { BaseReporter } from 'vitest/reporters';

367

368

class MetricsReporter extends BaseReporter {

369

private startTime: number = 0;

370

371

onInit() {

372

this.startTime = Date.now();

373

}

374

375

onFinished(files?: File[]) {

376

const duration = Date.now() - this.startTime;

377

const total = files?.reduce((acc, f) => acc + f.tasks.length, 0) || 0;

378

379

const passed = files?.reduce((acc, f) => {

380

return acc + f.tasks.filter(t => t.result?.state === 'pass').length;

381

}, 0) || 0;

382

383

console.log({

384

duration,

385

total,

386

passed,

387

passRate: (passed / total * 100).toFixed(2) + '%'

388

});

389

}

390

}

391

```

392

393

### Conditional Output

394

395

```typescript

396

import { BaseReporter } from 'vitest/reporters';

397

398

class QuietReporter extends BaseReporter {

399

onFinished(files?: File[], errors?: unknown[]) {

400

// Only output if there are errors

401

if (errors?.length) {

402

console.error(`Tests failed with ${errors.length} errors`);

403

errors.forEach(e => console.error(e));

404

}

405

}

406

}

407

```

408

409

## Type Definitions

410

411

```typescript { .api }

412

interface File {

413

filepath: string;

414

tasks: Task[];

415

result?: TaskResult;

416

}

417

418

interface Task {

419

id: string;

420

name: string;

421

mode: 'run' | 'skip' | 'only' | 'todo';

422

result?: TaskResult;

423

}

424

425

interface TaskResult {

426

state: 'pass' | 'fail' | 'skip';

427

duration?: number;

428

error?: Error;

429

}

430

431

interface Reporter {

432

onInit?(ctx: Vitest): void;

433

onPathsCollected?(paths?: string[]): void;

434

onCollected?(files?: File[]): Promise<void> | void;

435

onFinished?(files?: File[], errors?: unknown[]): Promise<void> | void;

436

onTaskUpdate?(task: [string, TaskResult | undefined][]): void;

437

}

438

```

439