Capstone Project: Building a Custom Vitest Plugin & Test Runner Reporter
Architecting a custom Vitest reporter and Vite plugin to measure test execution metrics.
Adetayo Akinsanya (unkletayo) • 2026-10-27
Part 14 in Series — Catch up on the previous article: Vitest Workspaces: Multi-Project Monorepo Test Execution Isolation (Part 13) before diving into this post.
In this capstone project, we build a custom Vitest reporter from scratch that hooks into test lifecycle events, tracks test execution durations, and exports metric reports.
// src/reporters/CustomMetricReporter.ts
import type { Reporter, TestCase, TestSuite, Vitest } from 'vitest/node';
import fs from 'node:fs';
export default class CustomMetricReporter implements Reporter {
private vitest!: Vitest;
private startTime: number = 0;
onInit(vitest: Vitest) {
this.vitest = vitest;
this.startTime = Date.now();
console.log('[MetricReporter] Initialized test runner instance...');
}
onFinished(files = [], errors = []) {
const duration = Date.now() - this.startTime;
const summary = {
totalFiles: files.length,
totalErrors: errors.length,
durationMs: duration,
timestamp: new Date().toISOString(),
};
fs.writeFileSync('test-metrics.json', JSON.stringify(summary, null, 2));
console.log(`[MetricReporter] Test run complete in ${duration}ms. Report saved.`);
}
}
Registering Custom Reporter in Config
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import CustomMetricReporter from './src/reporters/CustomMetricReporter';
export default defineConfig({
test: {
reporters: ['default', new CustomMetricReporter()],
},
});
This completes our 15-part series on Vitest architecture and modern testing mechanics.
Series Status
Part 15 in this series is scheduled for upcoming release on the daily publication roadmap.