Skip to content
← All posts
testing

Vitest and Playwright: a testing stack that fits Vite

When your apps build with Vite, Vitest is the unit runner that shares its pipeline, and Playwright covers the rest. Here is why that pairing works.

Vitest and Playwright cover
Published
Reading time
2 min read

Once we settled on Vite as our build tool, the testing stack almost picked itself: Vitest for unit and component tests, Playwright for end-to-end. Here is why that pairing fits, and how the two split the work.

Vitest speaks the same language as Vite

The reason Vitest is the natural companion is simple: it runs on top of Vite’s own config and transform pipeline. My tests are compiled the exact same way my app is. There is no second toolchain to configure, no separate Babel or transform setup that can drift from the real build, and no “works in the app but not in the test” surprises from mismatched compilation. TypeScript, path aliases, and the plugins that already work in the app just work in the tests too.

It is fast, and speed changes behavior

Vitest is ESM-native and only re-runs what changed in watch mode, so the feedback loop is tight enough that I actually keep tests running while I code. That matters more than it sounds. A fast suite gets run constantly; a slow one gets skipped until CI, which is exactly when you do not want to first discover a break.

Where Playwright takes over

Vitest is for logic and components in isolation. It cannot tell me whether the real thing works in a real browser: navigation, focus, keyboard, network timing, the actual rendered DOM. That is Playwright’s job. It drives real browsers, so the tests exercise the app the way a person does. I keep these fewer and focused on critical flows, because they are slower and more valuable per test.

The split, in practice

The shape is the classic pyramid. Most of the coverage is fast Vitest unit and component tests. A smaller layer of Playwright end-to-end tests guards the flows that must never break: booking, auth, and anything checkout-shaped. Each layer does what it is good at, and neither pretends to be the other.

Why not Jest

Jest is fine, but with a Vite app it means a parallel transform pipeline to maintain and keep in sync with the real build. Vitest removes that entire class of config drift by reusing what I already have. When the test runner and the build tool share a brain, there is simply less to go wrong.