SPB Git

spb/ultra-sharp-agent-skills Public

Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.

Python 100%
3.6 KB · 48 lines markdown
Rendered Raw Blame History
1---2name: testing-backend-services3description: Designs and writes tests for backend services — unit, integration with real dependencies in containers, contract tests, and minimal E2E — with deterministic, parallel-safe practices. Use when the user asks to test an API or service, write unit/integration/contract tests, fix flaky backend tests, set up testcontainers, or decide what to mock. Do not use for frontend or UI testing, or for load and performance testing.4---56<!--7Author: Simon-Pierre Boucher8Contact: contact@spboucher.ai9-->1011# Testing Backend Services1213## When to use / when NOT to use14- **Use for:** test strategy and test code for services and APIs: unit, integration, contract, E2E; de-flaking; test data design.15- **Do NOT use for:** browser/UI testing, or load/perf/soak testing — different tooling and goals.1617## Core rules18191. **Shape tests as a pyramid.** Many milliseconds-fast unit tests on pure logic; a solid layer of integration tests; one happy-path E2E per critical flow. Inverting it (E2E-heavy) buys slow, flaky suites.202. **Integration tests hit real dependencies in containers.** Spin up Postgres/Redis/broker via testcontainers.21   - ✅ test repository code against a real Postgres container22   - ❌ mock the database driver and assert SQL strings — that tests your mock.233. **Mock only what you don't own** (third-party HTTP APIs, clocks, randomness) — and pin those mocks with contract tests where possible.244. **Test behavior, not implementation.** Assert on outputs, state changes, and emitted events — not on which internal methods were called. Refactors must not break green tests.255. **No sleeps.** Poll with a timeout for async effects; freeze the clock for time logic; seed randomness. A test that needs `sleep(2)` is a race you scheduled.26   -`wait_until(lambda: outbox.count() == 1, timeout=5)`27   -`time.sleep(2); assert outbox.count() == 1`286. **Each test is independent and parallel-safe:** owns its data (unique IDs per test), never depends on execution order, cleans up via transaction rollback or per-test schema.297. **Factories over shared fixtures.** `make_user(email=...)` with overridable defaults beats a giant `fixtures.sql` that every test secretly depends on.308. **Contract tests guard API boundaries:** provider verifies it still satisfies consumer expectations (Pact or OpenAPI-based) on every CI run — cheaper than E2E across repos.3132## Workflow33341. Classify the change: pure logic → unit; touches DB/broker/HTTP edge → integration; crosses service boundary → contract; business-critical flow → one E2E.352. Write the test first at the lowest level that can catch the bug.363. Build test data with factories; give every entity a per-test unique key.374. Replace any sleep/order dependency with polling, frozen clocks, seeded RNG.385. Validate: run the suite twice — full run and `--last-failed` in random order (`pytest -p randomly`); both must pass. Run the new test 20× (`pytest --count=20 -x`) to prove it's not flaky.3940## Edge cases & failure modes41- **Test passes locally, fails in CI** → almost always shared state or timing; check for fixed ports, shared DB rows, real clock usage.42- **Container startup dominates runtime** → reuse one container per session with per-test transactions/schemas, not one container per test.43- **Untestable code** (network calls in constructors, global singletons) → refactor for injection first; don't monkey-patch around design problems.44- **Non-determinism sources** (UUIDs, now(), env) → inject them; asserting on wall-clock values is a flake factory.4546## References47Deeper recipes and gotchas: see [references/patterns.md](references/patterns.md)48