Vitest has two tools that go beyond ordinary behavior checking: benchmarks and in-source tests. Both are niche, both are easy to apply out of place, and both are useful when their narrow role is clear. A benchmark answers the question 'how fast is this', not 'is it correct'; an in-source test lets you keep a check right in the source. Neither replaces ordinary tests - it is an addition for specific cases.
A benchmark is written with the bench function instead of test. Under the hood Vitest uses tinybench and runs the function many times, gathering statistics: hz - operations per second, mean - the average time, p99 - the time within which 99% of runs fall, rme - the relative margin of error of the measurement. They are launched by a separate command, vitest bench, not by an ordinary run, because their purpose is different - measurement, not checking.
Several implementations of one algorithm are conveniently compared by grouping them in a plain describe: inside it each bench is measured under the same conditions, and Vitest shows them side by side with the fastest marked. This is how you compare, say, two versions of a parser or two deduplication strategies on real data. It is important to keep in mind that the mechanism is marked experimental: its API may change between versions, and tying CI gates to it is premature.
A benchmark's key limitation is that it is not a criterion of correctness. A fast implementation that gives a wrong result is useless, so bench does not cancel the ordinary test on the same behavior. The sensible order is this: first prove with tests that all compared versions are correct, and only then use a benchmark to pick the fastest among the correct ones. Measuring the performance of knowingly broken code is wasted time.
The second tool is in-source tests, checks right in the code file. They are written inside an if (import.meta.vitest) block, into which test and expect are imported from that same import.meta.vitest. In ordinary module execution import.meta.vitest equals undefined, so the block does not run; Vitest, under the includeSource option, sees it and runs it as tests residing in the same file as the function under check.
So that this block does not end up in the production bundle, the bundler strips it at build time: in the Vite config you set define substituting import.meta.vitest as undefined, and then the dead branch is removed by tree-shaking. This eliminates the main fear about the technique - that test code and Vitest imports will leak into the shipped package. With the right setup the user gets a clean module without a single test line.
In-source's appropriateness is narrow. It is good for small pure utilities where keeping the check next to the implementation is clearer than starting a separate file: a tiny formatting function, a parser of one format, a pure transformation. For full modules with many scenarios separate test files are still better - there in-source only clutters the source. It is a tool for the small and obvious, not a general style.
The typical failure with a benchmark is making decisions by it without ordinary tests and optimizing code that is in fact wrong. The second is forgetting about define with in-source and dragging the test block into the shipped bundle. And the common miss is applying both techniques wider than their niche: benchmarking what is not on the hot path, and stuffing in-source into modules that far more honestly deserve an ordinary test file nearby.
import { bench, describe } from 'vitest'
describe('deduplication', () => {
bench('via Set', () => { dedupeSet(data) })
bench('via reduce', () => { dedupeReduce(data) })
})
// vitest bench -> hz, mean, p99, rme; the fastest is markedexport function slugify(s: string) {
return s.trim().toLowerCase().replace(/\s+/g, '-')
}
if (import.meta.vitest) {
const { test, expect } = import.meta.vitest
test('slugify', () => expect(slugify(' Hello World ')).toBe('hello-world'))
}
// config: test.includeSource + define: { 'import.meta.vitest': 'undefined' }