vitest-best-practices

Installation
SKILL.md

Vitest Best Practices

Comprehensive patterns for writing maintainable, effective vitest tests. Focused on expert-level guidance for test organization, clarity, and performance.

NEVER Do When Writing Vitest Tests

  • NEVER skip global mock cleanup configuration - Manual cleanup appears safe but creates "action at a distance" failures: a mock in test file A leaks into test file B running 3 files later, causing non-deterministic failures that only appear when tests run in specific orders. These Heisenbugs waste hours in CI debugging. Configure clearMocks: true, resetMocks: true, restoreMocks: true in vitest.config.ts once to eliminate this entire class of order-dependent failure.
  • NEVER nest describe blocks more than 2 levels deep - Deep nesting creates cognitive overhead and excessive indentation. Put context in test names instead: it('should add item to empty cart') vs describe('when cart is empty', () => describe('addItem', ...)).
  • NEVER mock your own pure functions - Mocking internal code makes tests brittle and less valuable. Mock only external dependencies (APIs, databases, third-party libraries). Prefer fakes > stubs > spies > mocks.
  • NEVER use loose assertions like toBeTruthy() or toBeDefined() - These assertions pass for multiple distinct values you never intended: toBeTruthy() passes for 1, "false", [], and {} - all semantically different. When refactoring changes getUser() from returning {id: 1} to returning 1, your test still passes but your production code breaks. Loose assertions create false confidence that evaporates in production. toBeTypeOf() is NOT a loose assertion.
  • NEVER test implementation details instead of behavior - Tests that verify "function X was called 3 times" create false failures: you optimize code to call X once via memoization, all tests fail, yet the user experience is identical (and faster). These tests actively punish performance improvements and refactoring. Test what users observe (outputs given inputs), not how your code achieves it internally.
  • NEVER share mutable state between tests - Tests that depend on execution order or previous test state create flaky, unreliable suites. Each test must be fully independent with fresh setup.
  • NEVER use any or skip type checking in test files - When implementation signatures change, tests with as any silently pass while calling functions with wrong arguments. You ship broken code that TypeScript could have caught. Tests are executable documentation: user as any communicates nothing, but createTestUser(Partial<User>) shows exactly what properties matter for this test case.

Before Writing Tests, Ask

Apply these expert thinking patterns before implementing tests:

Related skills

More from gohypergiant/agent-skills

Installs
54
GitHub Stars
13
First Seen
Jan 21, 2026