ADR-004: Vitest over Jest
Date: 2024-01-01 Status: Accepted
Context
Testing framework selection needed to balance:
- TypeScript support
- Development experience
- Performance
- Integration with build tools
- Ecosystem maturity
Main contenders:
- Jest (proven, widely-used)
- Vitest (modern, TypeScript-first)
- Mocha + other tools (modular, but requires assembly)
Decision
We chose Vitest as the testing framework instead of Jest.
Rationale
- Vite Integration: Built on top of Vite, shares configuration
- TypeScript-First: Excellent out-of-the-box TypeScript support
- ESM Native: Full ES Modules support (Jest has limitations)
- Speed: Significantly faster test execution
- API Compatibility: Jest-like API, easy migration path
- Unified Config: Fewer configuration files to maintain
- Modern Codebase: Active development, regular updates
Performance Comparison
Jest: ~3-5 seconds for moderate test suite
Vitest: ~800ms-1.5s for same test suite
Consequences
Positive
- Faster test feedback loop
- Better TypeScript integration
- Native ESM support without transformations
- Easier configuration with existing Vite setup
- Better for monorepo testing
- Cleaner async/await support
Negative
- Smaller ecosystem than Jest
- Some legacy integrations may need adapters
- Newer tool, fewer Stack Overflow answers
- Some enterprise tools may lack Vitest support
Configuration Example
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
coverage: {
provider: 'v8',
reporter: ['text', 'html', 'lcov'],
lines: 80,
functions: 80,
branches: 75,
statements: 80,
},
},
});
Alternatives Considered
- Jest: Mature, widespread, but slower and harder TypeScript setup
- Mocha: Modular but requires manual setup and config
- Node's native test runner: Limited features, early stage
Migration Path (Jest → Vitest)
If switching back to Jest:
- Create
jest.config.js - Reinstall Jest and related packages
- Update test scripts in
package.json - Adjust imports if using Vitest-specific APIs
- Remove Vitest config
Most tests will work with minimal changes due to Jest API compatibility.
Testing Best Practices
import { describe, it, expect, beforeEach } from 'vitest';
describe('MyFunction', () => {
let result: any;
beforeEach(() => {
result = null;
});
it('should work correctly', () => {
result = myFunction();
expect(result).toBeDefined();
});
it('should handle errors', () => {
expect(() => myFunction(null)).toThrow();
});
});