Testing Strategy — Core Patterns, Vitest, Playwright & pytest
Testing patterns and conventions for Vitest, React Testing Library, MSW, Playwright, and pytest. Contains 46 rules across 12 categories, prioritized by impact. Focuses on patterns that produce reliable, maintainable tests — test isolation, mock boundaries, query priorities, meaningful coverage, E2E best practices, and Python testing fundamentals.
When to Apply
Reference these guidelines when:
- Writing new test files or test cases
- Reviewing test code for correctness and maintainability
- Deciding what to mock and what to test through
- Setting up test infrastructure (MSW, factories, fixtures)
- Configuring coverage thresholds or CI test pipelines
- Refactoring flaky or brittle tests
- Writing or reviewing Playwright E2E tests
- Configuring Playwright for CI or visual regression
- Writing pytest fixtures, parametrize tests, or conftest.py files
- Reviewing pytest code for isolation, async patterns, or parallelism
Target Versions
- Vitest 3.x
- React Testing Library 16.x
- MSW 2.x
- @testing-library/user-event 14.x
- Playwright 1.45+
- pytest 8.x
- anyio 4.x
- pytest-mock 3.x
- pytest-xdist 3.x
Rule Categories by Priority
| Priority |
Category |
Impact |
Prefix |
Rules |
| 1 |
Test Structure |
CRITICAL |
struct- |
5 |
| 2 |
Mocking Strategy |
HIGH |
mock- |
4 |
| 3 |
Vitest Patterns |
HIGH |
vitest- |
5 |
| 4 |
React Testing Library |
HIGH |
rtl- |
4 |
| 5 |
MSW & API Mocking |
MEDIUM-HIGH |
msw- |
3 |
| 6 |
Fixtures & Factories |
MEDIUM |
fixture- |
4 |
| 7 |
Coverage & CI |
MEDIUM |
ci- |
4 |
| 8 |
Snapshot Testing |
LOW-MEDIUM |
snap- |
3 |
| 9 |
Playwright Fundamentals |
HIGH |
pw- |
4 |
| 10 |
Playwright CI & Advanced |
MEDIUM |
pw- (shared) |
3 |
| 11 |
pytest Fundamentals |
HIGH |
pytest- |
4 |
| 12 |
pytest Advanced Patterns |
MEDIUM |
pytest- (shared) |
3 |
Quick Reference
1. Test Structure (CRITICAL)
struct-arrange-act-assert — Follow AAA pattern: setup, execute, verify in every test
struct-single-concept — Each test verifies one behavior, not multiple assertions on different things
struct-descriptive-names — Test names describe behavior: "shows error when email is invalid", not "test1"
struct-test-isolation — Tests must not depend on other tests' state or execution order
struct-no-logic — No conditionals, loops, or try/catch in tests — tests are straight-line code
2. Mocking Strategy (HIGH)
mock-boundaries — Mock at system boundaries (network, filesystem, time), not internal modules
mock-reset — Reset mocks between tests to prevent state leakage
mock-minimal — Mock the minimum needed — over-mocking makes tests pass when code is broken
mock-type-safety — Mocked return values must match the real type signature
3. Vitest Patterns (HIGH)
vitest-vi-mock — Use vi.mock for module mocking, vi.spyOn for method spying
vitest-test-each — Use test.each for parameterized tests instead of loops
vitest-setup-teardown — Use beforeEach/afterEach for per-test setup, beforeAll/afterAll for expensive shared setup
vitest-in-source — Use in-source testing for pure utility functions with no side effects and no more than 3 dependencies
vitest-fake-timers — Use vi.useFakeTimers for time-dependent code, always restore after
4. React Testing Library (HIGH)
rtl-query-priority — Query by role > label > text > testId. Avoid container.querySelector
rtl-user-event — Use userEvent over fireEvent for realistic user interaction simulation
rtl-async-queries — Use findBy for elements that appear asynchronously, waitFor for assertions
rtl-avoid-implementation — Test behavior, not implementation — don't assert on state or props
5. MSW & API Mocking (MEDIUM-HIGH)
msw-handlers — Define default handlers in a shared handlers file, override per-test for edge cases
msw-server-setup — Use setupServer in test setup, resetHandlers in afterEach, close in afterAll
msw-response-assertions — Assert on rendered output from API responses, not on whether fetch was called
6. Fixtures & Factories (MEDIUM)
fixture-factories — Use factory functions that return valid defaults with optional overrides
fixture-no-shared-mutation — Never mutate shared fixture objects — create fresh instances per test
fixture-realistic-data — Use realistic data shapes, not placeholder strings like "test" or "abc"
fixture-builders — Use builder pattern for complex objects with many optional fields
7. Coverage & CI (MEDIUM)
ci-meaningful-coverage — Measure branch coverage, not just line coverage. Target 80% as a floor, not a ceiling
ci-parallel-execution — Run tests in parallel by default; isolate tests that need serial execution
ci-flaky-quarantine — Quarantine flaky tests immediately, fix root cause, don't retry-and-ignore
ci-test-splitting — Split test suites across CI workers by file for faster pipelines
8. Snapshot Testing (LOW-MEDIUM)
snap-inline-small — Use inline snapshots for small outputs (< 10 lines), file snapshots for large
snap-avoid-large — Never snapshot entire component trees — snapshot the specific output that matters
snap-review-updates — Review every snapshot update in diffs — never blindly run --update
9. Playwright Fundamentals (HIGH)
pw-page-objects — Encapsulate page interactions in page object classes; expose behaviors, not selectors
pw-selectors — Prefer getByRole > getByLabel/getByText > getByTestId > CSS (mirrors rtl-query-priority)
pw-test-isolation — Each test gets a fresh browser context; no shared mutable state (cross-ref struct-test-isolation)
pw-fixtures — Use test.extend for custom fixtures; compose fixtures; use { scope: 'worker' } for expensive setup
10. Playwright CI & Advanced (MEDIUM)
pw-network-mocking — Use page.route() to intercept/stub network requests for deterministic E2E tests
pw-visual-regression — Screenshot specific components with toHaveScreenshot() + explicit thresholds (cross-ref snap-review-updates)
pw-ci-config — Browser projects, retries, trace: 'on-first-retry', artifact upload, --shard (cross-ref ci-test-splitting)
11. pytest Fundamentals (HIGH)
pytest-fixtures — Fixture scope (function/class/module/session), yield for teardown, fixture composition, autouse sparingly
pytest-parametrize — @pytest.mark.parametrize for data-driven tests, indirect fixtures, ids for readable output
pytest-conftest — conftest.py layering and discovery rules, scope-appropriate placement, keep test-specific fixtures local
pytest-mocking — monkeypatch for env vars/attrs/dicts, pytest-mock's mocker fixture, preference hierarchy vs raw unittest.mock
12. pytest Advanced Patterns (MEDIUM)
pytest-async — anyio for async tests, @pytest.mark.anyio, async fixtures, strict mode. Cross-ref: python-best-practices test-async-client for FastAPI-specific patterns
pytest-markers — Custom markers, marker registration in pyproject.toml, --strict-markers, filterwarnings
pytest-xdist — Parallel execution with pytest-xdist, --dist loadscope/loadfile, worker-safe fixtures. Cross-ref: ci-parallel-execution
Python Testing Note
For FastAPI-specific test patterns (async test clients, dependency overrides, database isolation), see the python-best-practices skill. The pytest rules here cover general patterns applicable to any Python project.
Linting & Formatting
For ESLint test plugins (eslint-plugin-testing-library, eslint-plugin-vitest, eslint-plugin-playwright) and other tooling, see the code-quality skill.
Full Compiled Document
For the complete guide with all rules expanded and code examples: AGENTS.md
1---2name: testing-strategy3description: Use when writing, reviewing, or refactoring test code. Triggers on Vitest tests, React Testing Library usage, MSW handlers, Playwright E2E tests, pytest fixtures, test structure decisions, or coverage configuration. Contains 46 testing rules across 12 categories.4---56# Testing Strategy — Core Patterns, Vitest, Playwright & pytest78Testing patterns and conventions for Vitest, React Testing Library, MSW, Playwright, and pytest. Contains 46 rules across 12 categories, prioritized by impact. Focuses on patterns that produce reliable, maintainable tests — test isolation, mock boundaries, query priorities, meaningful coverage, E2E best practices, and Python testing fundamentals.910## When to Apply1112Reference these guidelines when:13- Writing new test files or test cases14- Reviewing test code for correctness and maintainability15- Deciding what to mock and what to test through16- Setting up test infrastructure (MSW, factories, fixtures)17- Configuring coverage thresholds or CI test pipelines18- Refactoring flaky or brittle tests19- Writing or reviewing Playwright E2E tests20- Configuring Playwright for CI or visual regression21- Writing pytest fixtures, parametrize tests, or conftest.py files22- Reviewing pytest code for isolation, async patterns, or parallelism2324## Target Versions2526- Vitest 3.x27- React Testing Library 16.x28- MSW 2.x29- @testing-library/user-event 14.x30- Playwright 1.45+31- pytest 8.x32- anyio 4.x33- pytest-mock 3.x34- pytest-xdist 3.x3536## Rule Categories by Priority3738| Priority | Category | Impact | Prefix | Rules |39|----------|----------|--------|--------|-------|40| 1 | Test Structure | CRITICAL | `struct-` | 5 |41| 2 | Mocking Strategy | HIGH | `mock-` | 4 |42| 3 | Vitest Patterns | HIGH | `vitest-` | 5 |43| 4 | React Testing Library | HIGH | `rtl-` | 4 |44| 5 | MSW & API Mocking | MEDIUM-HIGH | `msw-` | 3 |45| 6 | Fixtures & Factories | MEDIUM | `fixture-` | 4 |46| 7 | Coverage & CI | MEDIUM | `ci-` | 4 |47| 8 | Snapshot Testing | LOW-MEDIUM | `snap-` | 3 |48| 9 | Playwright Fundamentals | HIGH | `pw-` | 4 |49| 10 | Playwright CI & Advanced | MEDIUM | `pw-` (shared) | 3 |50| 11 | pytest Fundamentals | HIGH | `pytest-` | 4 |51| 12 | pytest Advanced Patterns | MEDIUM | `pytest-` (shared) | 3 |5253## Quick Reference5455### 1. Test Structure (CRITICAL)5657- `struct-arrange-act-assert` — Follow AAA pattern: setup, execute, verify in every test58- `struct-single-concept` — Each test verifies one behavior, not multiple assertions on different things59- `struct-descriptive-names` — Test names describe behavior: "shows error when email is invalid", not "test1"60- `struct-test-isolation` — Tests must not depend on other tests' state or execution order61- `struct-no-logic` — No conditionals, loops, or try/catch in tests — tests are straight-line code6263### 2. Mocking Strategy (HIGH)6465- `mock-boundaries` — Mock at system boundaries (network, filesystem, time), not internal modules66- `mock-reset` — Reset mocks between tests to prevent state leakage67- `mock-minimal` — Mock the minimum needed — over-mocking makes tests pass when code is broken68- `mock-type-safety` — Mocked return values must match the real type signature6970### 3. Vitest Patterns (HIGH)7172- `vitest-vi-mock` — Use vi.mock for module mocking, vi.spyOn for method spying73- `vitest-test-each` — Use test.each for parameterized tests instead of loops74- `vitest-setup-teardown` — Use beforeEach/afterEach for per-test setup, beforeAll/afterAll for expensive shared setup75- `vitest-in-source` — Use in-source testing for pure utility functions with no side effects and no more than 3 dependencies76- `vitest-fake-timers` — Use vi.useFakeTimers for time-dependent code, always restore after7778### 4. React Testing Library (HIGH)7980- `rtl-query-priority` — Query by role > label > text > testId. Avoid container.querySelector81- `rtl-user-event` — Use userEvent over fireEvent for realistic user interaction simulation82- `rtl-async-queries` — Use findBy for elements that appear asynchronously, waitFor for assertions83- `rtl-avoid-implementation` — Test behavior, not implementation — don't assert on state or props8485### 5. MSW & API Mocking (MEDIUM-HIGH)8687- `msw-handlers` — Define default handlers in a shared handlers file, override per-test for edge cases88- `msw-server-setup` — Use setupServer in test setup, resetHandlers in afterEach, close in afterAll89- `msw-response-assertions` — Assert on rendered output from API responses, not on whether fetch was called9091### 6. Fixtures & Factories (MEDIUM)9293- `fixture-factories` — Use factory functions that return valid defaults with optional overrides94- `fixture-no-shared-mutation` — Never mutate shared fixture objects — create fresh instances per test95- `fixture-realistic-data` — Use realistic data shapes, not placeholder strings like "test" or "abc"96- `fixture-builders` — Use builder pattern for complex objects with many optional fields9798### 7. Coverage & CI (MEDIUM)99100- `ci-meaningful-coverage` — Measure branch coverage, not just line coverage. Target 80% as a floor, not a ceiling101- `ci-parallel-execution` — Run tests in parallel by default; isolate tests that need serial execution102- `ci-flaky-quarantine` — Quarantine flaky tests immediately, fix root cause, don't retry-and-ignore103- `ci-test-splitting` — Split test suites across CI workers by file for faster pipelines104105### 8. Snapshot Testing (LOW-MEDIUM)106107- `snap-inline-small` — Use inline snapshots for small outputs (< 10 lines), file snapshots for large108- `snap-avoid-large` — Never snapshot entire component trees — snapshot the specific output that matters109- `snap-review-updates` — Review every snapshot update in diffs — never blindly run --update110111### 9. Playwright Fundamentals (HIGH)112113- `pw-page-objects` — Encapsulate page interactions in page object classes; expose behaviors, not selectors114- `pw-selectors` — Prefer `getByRole` > `getByLabel`/`getByText` > `getByTestId` > CSS (mirrors `rtl-query-priority`)115- `pw-test-isolation` — Each test gets a fresh browser context; no shared mutable state (cross-ref `struct-test-isolation`)116- `pw-fixtures` — Use `test.extend` for custom fixtures; compose fixtures; use `{ scope: 'worker' }` for expensive setup117118### 10. Playwright CI & Advanced (MEDIUM)119120- `pw-network-mocking` — Use `page.route()` to intercept/stub network requests for deterministic E2E tests121- `pw-visual-regression` — Screenshot specific components with `toHaveScreenshot()` + explicit thresholds (cross-ref `snap-review-updates`)122- `pw-ci-config` — Browser projects, retries, `trace: 'on-first-retry'`, artifact upload, `--shard` (cross-ref `ci-test-splitting`)123124### 11. pytest Fundamentals (HIGH)125126- `pytest-fixtures` — Fixture scope (function/class/module/session), yield for teardown, fixture composition, autouse sparingly127- `pytest-parametrize` — `@pytest.mark.parametrize` for data-driven tests, indirect fixtures, `ids` for readable output128- `pytest-conftest` — conftest.py layering and discovery rules, scope-appropriate placement, keep test-specific fixtures local129- `pytest-mocking` — `monkeypatch` for env vars/attrs/dicts, `pytest-mock`'s `mocker` fixture, preference hierarchy vs raw `unittest.mock`130131### 12. pytest Advanced Patterns (MEDIUM)132133- `pytest-async` — anyio for async tests, `@pytest.mark.anyio`, async fixtures, strict mode. Cross-ref: python-best-practices `test-async-client` for FastAPI-specific patterns134- `pytest-markers` — Custom markers, marker registration in `pyproject.toml`, `--strict-markers`, `filterwarnings`135- `pytest-xdist` — Parallel execution with pytest-xdist, `--dist loadscope`/`loadfile`, worker-safe fixtures. Cross-ref: `ci-parallel-execution`136137## Python Testing Note138139For FastAPI-specific test patterns (async test clients, dependency overrides, database isolation), see the **python-best-practices** skill. The pytest rules here cover general patterns applicable to any Python project.140141## Linting & Formatting142143For ESLint test plugins (eslint-plugin-testing-library, eslint-plugin-vitest, eslint-plugin-playwright) and other tooling, see the **code-quality** skill.144145## Full Compiled Document146147For the complete guide with all rules expanded and code examples: `AGENTS.md`