database-testing
Skill8 starsChanged 9 days agoMITView on GitHub
Sets up fast, isolated tests against a real database engine - Testcontainers or CI service containers, per-test isolation (rollback, truncate, template databases), factories instead of large fixtures, migration tests, and tests for constraints, triggers, queries and query counts. Use when writing tests that touch a database, replacing an in-memory or SQLite test database, fixing slow or order-dependent database tests, or adding tests for migrations.
- Deletes or force-pushes
6 other projects use a version of this.
Adopted by
Most recently taken up by
- jason0971/skillstheir own version, first seen Nov 8, 2026
- petrkindlmann/qa-skillstheir own version, first seen Oct 25, 2026
- proffesor-for-testing/agentic-qetheir own version, first seen Oct 25, 2026
- mejbaurbahar/software-tester-skillstheir own version, first seen Oct 13, 2026
- CaduS0uza/qa-supremetheir own version, first seen Sep 10, 2026
- mejbaurbahar/faguntheir own version, first seen Jul 5, 2026
Other versions6 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 6
- proffesor-for-testing/agentic-qe★ 524same name
- petrkindlmann/qa-skills★ 209same name
- CaduS0uza/qa-supreme★ 1same name
- jason0971/skills★ 1same name
- mejbaurbahar/fagun★ 1same name
- mejbaurbahar/software-tester-skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository60 other files it gives its agents.
- api-designSkill
- auth-implementationSkill
- background-jobsSkill
- building-agentsSkill
- caching-strategiesSkill
- ci-cd-pipelinesSkill
- cloud-cost-optimizationSkill
- codebase-onboardingSkill
- code-review-changesSkill
- concurrency-patternsSkill
- database-migrationsSkill
- database-schema-designSkill
- data-pipelinesSkill
- data-privacy-retentionSkill
- dependency-upgradesSkill
- design-docsSkill
- design-systemsSkill
- dockerfilesSkill
- domain-driven-designSkill
- event-driven-architectureSkill
- file-storage-uploadsSkill
- frontend-securitySkill
- git-workflowSkill
- graphql-apisSkill
- grpc-servicesSkill
- incident-responseSkill
- infrastructure-as-codeSkill
- internationalizationSkill
- kubernetes-deploymentsSkill
- large-scale-migrationsSkill
- legacy-refactoringSkill
- llm-evalsSkill
- llm-integrationSkill
- mcp-serversSkill
- micro-frontendsSkill
- ml-experimentsSkill
- monorepo-managementSkill
- nosql-designSkill
- observabilitySkill
- orm-patternsSkill
- performance-profilingSkill
- postgres-operationsSkill
- rag-systemsSkill
- react-patternsSkill
- realtime-apisSkill
- resilience-patternsSkill
- root-cause-debuggingSkill
- search-integrationSkill
- security-auditSkill
- seo-and-ssrSkill
- sql-optimizationSkill
- system-designSkill
- test-strategySkill
- threat-modelingSkill
- typescript-patternsSkill
- unit-testingSkill
- verify-before-doneSkill
- web-accessibilitySkill
- web-performanceSkill
- writing-skillsSkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 6 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 6 edited versions we read keep these.
6
Distinctive
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
- Distinctive: line 18
Not for: unit tests of pure logic (no database at all.
- Distinctive: line 51
Default: rollback per test for repository-level tests, truncate or template for tests that exercise code which commits, plus one database …
- Distinctive: line 65
Data migrations and backfills: test them with edge-case rows (NULLs, empty strings, duplicates, very long values, legacy formats), and …
- Distinctive: line 66
Slow migrations: test duration and locking on a production-sized copy outside the unit test suite (see the database-migrations skill).
- Very specific: line 71
Triggers, functions, row-level security: test as the role the application uses, with tenant settings applied exactly as the application …
- Distinctive: line 78
Add a check that runs before any test touches the database and fails the run unless the target is clearly a test database, for example:
- Distinctive: line 89
Schema built by the ORM's "create all": instead of the migrations.
“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Database Testing
Test against the same database engine and major version that production runs. In-memory substitutes (SQLite standing in for PostgreSQL, H2 for MySQL, ORM in-memory providers) accept queries production rejects and reject ones it accepts, and they don't enforce the same constraints, types or locking. Tests that pass on them prove little about the real system.
When to use
- Writing integration tests for repositories, queries, ORM mappings or database logic.
- Moving off an in-memory or SQLite test database.
- Database tests are slow, flaky, or fail when run in a different order or in parallel.
- Adding a safety net for schema migrations.
Not for: unit tests of pure logic (no database at all; see test-strategy), load testing, or tuning production queries (sql-optimization).
Workflow
- Match production: same engine, same major version, same extensions. Pin the image tag (for example
postgres:16-alpineif production is PostgreSQL 16). - Provide the database with Testcontainers in the test code, or a service container in CI. Examples per stack: references/setup-examples.md.
- Build the schema with the real migrations, not the ORM's "create all tables" shortcut, so the tests also prove the migrations work.
- Choose an isolation strategy (table below) so every test starts from a known state and tests can run in any order.
- Create data per test with factories, only what the test needs.
- Add migration tests and query-count assertions for risky paths.
- Add a guard so the test suite refuses to run against anything but a local or test database.
Providing a real database
| Option | Good for | Notes |
| Testcontainers (Java, .NET, Go, Node, Python and others) | Tests that start their own database anywhere Docker runs | Start one container per test session or worker, not per test |
CI service containers (GitHub Actions services:, GitLab services:) | Simple pipelines | Local runs need a matching local setup (compose file) |
docker compose with a test profile | Teams that also run the app locally in Docker | Keep it separate from the dev database |
| Managed cloud test instance | Features you can't run in a container | Never share it with other environments |
Speed settings for throwaway test PostgreSQL only (they trade crash safety for speed): start the server with -c fsync=off -c synchronous_commit=off -c full_page_writes=off, and optionally keep the data directory on tmpfs. Never use these settings on any database that holds real data.
Isolation strategies
| Strategy | How | Speed | Limits |
| Transaction rollback per test | Open a transaction before the test, roll back after (Django TestCase, Rails transactional tests, Spring @Transactional tests) | Fastest | Code under test can't commit or use other connections; misses commit-time behavior (deferred constraints, triggers on commit, on_commit hooks) |
| Truncate between tests | TRUNCATE t1, t2 ... RESTART IDENTITY CASCADE (PostgreSQL) after each test or class | Fast enough for most suites | Order of tables and foreign keys matters on some engines; reference data must be re-seeded |
| Template database per test or worker | Migrate once into app_template, then CREATE DATABASE test_n TEMPLATE app_template (PostgreSQL) | Fast clones | The template must have no open connections while cloning |
| Database or schema per parallel worker | Name it after the worker id (app_test_gw3) | Enables parallel runs | Combine with one of the strategies above inside each worker |
| Fresh container per test class | New container each time | Slow | Only for tests that change server-level settings |
Default: rollback per test for repository-level tests, truncate or template for tests that exercise code which commits, plus one database per worker when running in parallel.
Test data
- Factories or builders per test (for example factory_boy, FactoryBot, Bogus, or plain builder functions). Each test creates exactly the rows it asserts on, with defaults for everything else.
- Small, named reference data (countries, plans) can be seeded once by a migration or a seed script that is part of the test setup.
- No production dumps. They contain personal data (see data-privacy-retention), are slow to load, and make tests depend on data nobody understands.
- Don't depend on generated IDs, row order without
ORDER BY, or the current time. Use the IDs returned by the insert, add explicit ordering, and inject a fixed clock.
Migration tests
- From empty: apply every migration to an empty database and run the suite. Then check that the ORM's model and the migrated schema agree, using the tool's check command where it exists (for example
python manage.py makemigrations --check --dry-run,alembic check,prisma migrate diff; check the docs for your tool). - Upgrade from the last release: restore the previous release's schema (and a little representative data), apply only the new migrations, and run smoke tests. This catches migrations that only work on an empty database.
- Down migrations, if the project uses them: run up, down, up again.
- Data migrations and backfills: test them with edge-case rows (NULLs, empty strings, duplicates, very long values, legacy formats), and assert the result, not only "no error".
- Slow migrations: test duration and locking on a production-sized copy outside the unit test suite (see the database-migrations skill).
What to test in the database itself
- Constraints: insert a duplicate and assert the unique violation; insert an orphan and assert the foreign key error; check CHECK constraints at their edges.
- Triggers, functions, row-level security: test as the role the application uses, with tenant settings applied exactly as the application sets them (for example
SET LOCAL app.tenant_id = '<tenant uuid>'inside the test transaction, matching the policy in the database-schema-design skill), and assert that other tenants' rows are invisible. - Tricky queries: time zones and daylight saving boundaries, NULL handling, pagination stability with ties, case sensitivity and collation.
- Concurrency: open two connections and assert that the lock or optimistic version check behaves as designed (two transactions decrementing the same stock must not both succeed).
- Query counts: assert the number of statements a code path runs, to stop N+1 regressions (see orm-patterns).
Safety guard
Add a check that runs before any test touches the database and fails the run unless the target is clearly a test database, for example:
- the host is
localhost, a container host, or a CI service name, and - the database name ends in
_test, and - an explicit environment variable such as
APP_ENV=testis set.
Tests truncate and drop tables. Never point a test suite at a shared, staging or production database, and stop and ask the user if the configured database looks like one.
Anti-patterns
- In-memory or SQLite substitutes for a different production engine.
- Schema built by the ORM's "create all" instead of the migrations.
- One giant shared fixture that every test depends on and nobody can change.
- Tests that depend on each other or on run order (test B relies on rows from test A).
- Asserting on auto-increment IDs or unordered result order.
- Restarting the database container for every test.
- Sleeping to wait for the database instead of a readiness check (Testcontainers wait strategies,
pg_isready, CI health checks).
Done when
- Tests run against the production engine and major version, with the schema built from migrations.
- Each test creates its own data and passes in any order, alone, and in parallel.
- Migrations are tested from empty and as an upgrade from the previous release.
- Constraints, permissions and critical queries have direct tests; key paths have query-count assertions.
- The suite refuses to run against non-test databases.
- The database portion of the suite runs fast enough that developers run it before pushing.
References
- references/setup-examples.md — read when wiring up the database for tests: Testcontainers in Java/Spring, Python, Node, .NET and Go, a GitHub Actions service container, and template-database and truncate helpers.
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
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.

