Files
upstream-atomic-crm/.claude/rules/testing.md
upstream-mirror 93ecc1a6f8
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:48:50 +05:00

2.9 KiB

paths
paths

Testing

Minimum coverage: 80%

New code paths without tests are a blocking issue in code review. But coverage is a FLOOR, not a target: never write a test just to reach the number (that is what produces filler tests). Pertinence outranks the percentage.

Pertinence: test behavior, not implementation

  • Assert user-observable behavior / rendered output (Testing Library principle: "the more your tests resemble the way the software is used, the more confidence they give"). Never assert internal state, props, private methods, or merely that a mock was called.
  • Weight toward integration for this React app (the Testing Trophy): a component with its real collaborators over many shallow unit tests. Never test the framework or a third-party library.
  • Delete a test ONLY for lack of intrinsic value (cannot name a realistic bug it would catch, tautological, implementation-detail, snapshot-only, redundant with a better test), NEVER because "the code works now" or to cap the count: a passing test exists to guard FUTURE regressions. Shrink the suite by CONSOLIDATING redundancy, not by deleting coverage.
  • Forbidden (blocking in review): asserting a mock returns its configured value; a snapshot as the primary assertion; reading component state / props / internals; a test written only to raise the coverage number.

TDD orientation: acceptance-test-driven

  • Derive each test from the ticket's acceptance_criteria; every test should map to a criterion or a user-visible behavior. A test with no traceable criterion is filler.
  • Enforce the OUTCOME (behavior tests present and green), not literal red-green ordering (unverifiable when one agent writes both the test and the code).

Test structure — AAA pattern

Prefer Arrange-Act-Assert for all tests:

test('calculates similarity correctly', () => {
  // Arrange
  const input = buildInput()

  // Act
  const result = compute(input)

  // Assert
  expect(result).toBe(expected)
})

Test naming

Use descriptive names that explain the behavior under test:

  • returns empty array when no items match the query
  • throws error when required field is missing
  • falls back to default value when API is unavailable

Avoid: test1, testFoo, should work.

Test isolation

Each test must be independent — no shared mutable state. No test should depend on the execution order of other tests. Reset mocks and fixtures in beforeEach, not globally.

E2E shape (Playwright)

import { test, expect } from '@playwright/test'

test('ticket list loads', async ({ page }) => {
  await page.goto('/tickets')
  await expect(page.locator('h1')).toBeVisible()
})

Never use timeout-based assertions (waitForTimeout). Always prefer deterministic waits: waitForResponse, waitForSelector, expect(locator).toBeVisible(). Flaky tests must be quarantined with test.fixme() and a tracking reference before merge.