Files
skills/common/engineering/tdd/tests.md
T
gitadmin 68f9b4691e feat(skills): add engineering skill definitions under common/engineering/ all from @mattpocock
Add 10 skill definitions covering codebase design, domain modeling,
test-driven development, triage, and development workflows:

- codebase-design: vocabulary and patterns for designing deep modules
- domain-modeling: build and sharpen project domain models
- grill-with-docs: interview-based design refinement with documentation
- improve-codebase-architecture: scan and report on deepening opportunities
- resolving-merge-conflicts: structured approach to merge/rebase conflicts
- setup-skills: per-repo configuration for engineering skills
- tdd: test-driven development workflow with vertical slices
- to-issues: break plans into tracer-bullet vertical slice issues
- to-prd: synthesize conversations into PRDs
- triage: state machine for issue/PR triage roles

Includes supporting files for ADR formats, issue tracker integrations
(GitHub, GitLab, Gitea), triage labels, and agent brief templates.
2026-06-25 12:01:55 -04:00

1.6 KiB

Good and Bad Tests

Good Tests

Integration-style: Test through real interfaces, not mocks of internal parts.

// GOOD: Tests observable behavior
test("user can checkout with valid cart", async () => {
  const cart = createCart();
  cart.add(product);
  const result = await checkout(cart, paymentMethod);
  expect(result.status).toBe("confirmed");
});

Characteristics:

  • Tests behavior users/callers care about
  • Uses public API only
  • Survives internal refactors
  • Describes WHAT, not HOW
  • One logical assertion per test

Bad Tests

Implementation-detail tests: Coupled to internal structure.

// BAD: Tests implementation details
test("checkout calls paymentService.process", async () => {
  const mockPayment = jest.mock(paymentService);
  await checkout(cart, payment);
  expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
});

Red flags:

  • Mocking internal collaborators
  • Testing private methods
  • Asserting on call counts/order
  • Test breaks when refactoring without behavior change
  • Test name describes HOW not WHAT
  • Verifying through external means instead of interface
// BAD: Bypasses interface to verify
test("createUser saves to database", async () => {
  await createUser({ name: "Alice" });
  const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
  expect(row).toBeDefined();
});

// GOOD: Verifies through interface
test("createUser makes user retrievable", async () => {
  const user = await createUser({ name: "Alice" });
  const retrieved = await getUser(user.id);
  expect(retrieved.name).toBe("Alice");
});