writing-tests

SKILL.md

Writing Tests

Test behavior, not implementation. Prioritize by risk.

When to Use Each Type

Type What When Tools
Unit Single function/hook Pure logic, calculations Vitest, Jest
Integration Component + deps Forms, data display Testing Library
E2E Full user flow Critical paths Playwright

Always Test

  • Auth flows
  • Payment/checkout
  • Data mutations (create, update, delete)
  • Authorization rules
  • Critical business logic

Rarely Test

  • Static content
  • Third-party internals
  • Pure styling

File Organization

src/components/Button/
├── Button.tsx
└── Button.test.tsx      # Colocated

e2e/                     # E2E at root
├── auth.spec.ts
└── checkout.spec.ts

Patterns

Arrange-Act-Assert

test('increments on click', () => {
  // Arrange
  render(<Counter initial={0} />)
  // Act
  fireEvent.click(screen.getByRole('button'))
  // Assert
  expect(screen.getByText('1')).toBeInTheDocument()
})

Query Priority (best → worst)

  1. getByRole - semantic, accessible
  2. getByLabelText - form inputs
  3. getByText - content
  4. getByTestId - last resort

Test Behavior, Not Implementation

// ❌ Implementation
expect(component.state.isOpen).toBe(true)

// ✅ Behavior
expect(screen.getByRole('dialog')).toBeVisible()

Minimum Viable Testing

If time-constrained:

  1. E2E for happy paths (covers most ground)
  2. Unit for complex logic (catches edge cases)
  3. Integration for critical components (forms, data)

Advanced Patterns

For API mocking, test fixtures, and coverage guidance, see MOCKING.md.

Weekly Installs
2
First Seen
2 days ago
Installed on
opencode2
codex2
claude-code2
antigravity2
gemini-cli2
windsurf1