agentleFS
VelimirMuellerVelimirMueller/ai-development-skills/skills/backend/configure-backend-tests/SKILL.md

configure-backend-tests

Skill7 starsChanged 16 days agoMITView on GitHub

Use when a backend service needs a test setup or its tests mock the database. Builds the pyramid - pure unit tests, real-Postgres integration via testcontainers, HTTP-level tests, OpenAPI contract tests, factories and CI-ready layout (Vitest, go test, pytest).

  • Installs packages

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    No test config and no tests/: full setup, steps 3 to 7.

    line 28
  2. Distinctive:

    Create from test-tracks.md, skipping files that exist:

    line 57
  3. Distinctive:

    Conformance: Run schemathesis against the running app:

    line 81

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Configure Backend Tests

Rules and rationale: test-patterns.md. Code per track: test-tracks.md. Layout follows the tests rows of service-layout.md. The principle behind it all: "Tests at the boundary that pays" in engineering-principles.md.

1. Audit (change nothing)

cat .claude/stack-profile.md ~/.claude/stack-profile.md 2>/dev/null   # backend.track, tests.layout (tests-dir|colocated), database.engine
ls tests tests/unit tests/integration vitest.config.ts pyproject.toml 2>/dev/null
grep -rnE "vi\.mock\('pg|jest\.mock|sqlsmock|DATA-DOG/go-sqlmock" --include=*.ts --include=*.go . 2>/dev/null | grep -v node_modules
grep -rnE "unittest\.mock" --include=*.py . 2>/dev/null | grep -iE "patch.*(session|engine|pool)"
grep -rnE "sleep\(" --include=*.ts --include=*.go --include=*.py tests src internal 2>/dev/null   # sleep-based waits
docker info >/dev/null 2>&1 && echo "docker: ok" || echo "docker: missing"
  • The DB-mock grep (vi.mock('pg, jest.mock, sqlsmock, DATA-DOG/go-sqlmock, unittest.mock patching a session) is the main finding: those tests verify an assumption about the SQL, not the SQL. They move to real-Postgres integration tests.
  • Sleep-based waits are the second finding: they are the flake source in CI.
  • docker info failing means the container runtime is absent: the integration suites cannot run on this machine. Install everything; verify unit tests only, and say so.
  • The support modules assume database.engine: postgres (TRUNCATE over pg_tables, the testcontainers Postgres module). Another engine means adapting the reset, not the pattern.

2. Decide

  • No test config and no tests/: full setup, steps 3 to 7.
  • Tests exist but mock the database or sleep: delta. Add the support modules from test-tracks.md, move the DB-touching tests into the integration project or suite, replace sleeps with condition waits. Keep sound unit tests where they are.
  • Vitest projects (unit, integration), Go TestMain with a container and the pytest integration marker all present, no DB mocks, step 7 green: report "already in place" and stop.

3. Detect track and layout

backend.trackTest stack
honoVitest 5 projects: unit, integration
gogo test: unit tests beside the code (*_test.go), integration and HTTP tests in tests/
fastapipytest with tests/unit, tests/integration, marker integration
nextjsStop. Use build-nextjs-backend.
supabaseStop. Use secure-supabase-rls; its test side is rls-test-patterns.md.
none or unsetRun set-up-stack-profile, then a scaffold-*-service skill.

tests.layout decides where unit tests live: tests-dir (default) -> tests/{unit,integration,support}; colocated -> TS unit tests in src/**/*.test.ts (change the unit project's include), integration stays in tests/integration. Go keeps unit tests beside the code whatever the profile says (service-layout.md). The worked example is the documents module of set-up-backend-auth; rename it or delete it once a real module uses the shape.

4. Install only what is missing

pnpm add -D vitest @testcontainers/postgresql   # hono; add @types/pg too when the app uses pg
go get github.com/testcontainers/testcontainers-go/modules/postgres github.com/go-jose/go-jose/v4   # go: container + test-token signing
uv add --dev testcontainers "psycopg[binary]"     # fastapi: plain testcontainers, no [postgres] extra

Python imports the container from testcontainers.community.postgres (testcontainers.postgres is deprecated). psycopg is the one driver: the container URL (postgresql+psycopg://) drives the migration pass and the app engine unchanged — no URL rewriting between them. Use the profile's package manager. Versions: stack-versions.md.

5. Generate

Create from test-tracks.md, skipping files that exist:

tests/support/      container start, db reset, IdP tokens, app builder, factories
config              vitest projects / pytest markers (Go needs none: TestMain)
first unit test     a policy or pure service function
first integration   one resource through HTTP against real Postgres

The container is migrated with the repo's real migrations — set-up-database owns them; the worked example ships its own drizzle/0000_init.sql / migrations/0001_init.sql.

Scripts — unit tests are the fast loop, integration joins on demand or in CI:

  • TS package.json: "test": "vitest run", "test:unit": "vitest run --project unit", "test:integration": "vitest run --project integration".
  • Go: go test ./internal/... for the fast loop; go test ./... for all of it, tests/ included.
  • Python: uv run pytest -m "not integration" for units; uv run pytest for everything.

6. Wire into CI and contract checks

One job per track: unit tests first (fail fast), then integration in the same job — the ubuntu-latest runners have Docker, and testcontainers starts its own Postgres, so no service container is needed. The workflow with SHA-pinned actions is in test-tracks.md ("CI job").

Contract tests, two kinds:

  1. Spec drift. Generate the OpenAPI document and compare with the committed copy at contracts/openapi.json; fail the step when they differ. TS: pnpm openapi (via scripts/print-openapi.ts), then diff openapi.json contracts/openapi.json. Python: dump app.openapi(). Go: openapi.yaml is hand-written or the oapi-codegen source, so drift is a regenerate-and-diff. The Hono scaffold git-ignores openapi.json; that is why the committed copy uses the contracts/ name.
  2. Conformance. Run schemathesis against the running app:
schemathesis run http://localhost:PORT/openapi.json --checks all -n 25 --exclude-path '/documents/{doc_id}'

Verified on the FastAPI scaffold: 55 generated, 55 passed — but only after the first run found a real bug (a 405 without an Allow header). Protected endpoints: add -H "Authorization: Bearer $TOKEN". In CI, start the app in the background and pass --wait-for-schema 30.

7. Verify

pnpm test       # hono
go test ./...   # go
uv run pytest   # fastapi

Expected: all green. The worked example: 3 unit files + 1 integration file (TS), and 6 integration cases per track — own tenant 200, other tenant 404, missing scope 403, no token 401, wrong audience 401, malformed id 400; the Go and Python files add an expired-token 401 case. The first integration run pulls the postgres:18 image and is slower; with the image cached, the full suite took 15-16 s locally. A second run of this skill changes nothing.

References

  • test-patterns.md: the pyramid, real Postgres over mocks, HTTP-level tests, fakes, naming, CI rules, what not to test.
  • test-tracks.md: every file for Vitest, go test and pytest, plus the CI job.
  • auth-patterns.md: the policies and tenant scoping these tests prove.
  • configure-test-stack: the frontend side; browser-level tests live there.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.