pgLab/.junie/skills/pg-integration-tests/SKILL.md

43 lines
3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: pg-integration-tests
description: Write and run pgLab tests against a real PostgreSQL server (14–17) using the pgintegration harness (DbTest fixture, template database, REQUIRE_PG_AT_LEAST). Use whenever a test needs a live server, e.g. catalog introspection, generated SQL that must be executed, version-specific behaviour, or when the user mentions integration tests, IntegrationTests, docker-compose Postgres or TEST_DATABASE_URL.
---
# Integration tests against real PostgreSQL
Build/run commands live in `AGENTS.md` (Build and test); don't duplicate them here.
## When to use
Use for behaviour that depends on a real server: catalog queries, `pg_get_*` output, executing generated SQL, version differences. Pure string/logic tests belong in `PgsqlTests` / `pglabtests` instead.
## Layout
- `tests/pgintegration/` – static lib: `PgEnv` (global environment, builds template DB `tmpl_<pid>` from `fixtures/schema.sql`), `DbTest` fixture, helpers.
- `tests/integration/` – `IntegrationTests` executable, `tst_*.cpp`, `fixtures/schema.sql`, `docker-compose.yml`.
- The binary only reads `TEST_DATABASE_URL`; unset means every `DbTest` skips.
## Writing a test
```cpp
#include "DbTest.h"
#include "PgTestEnvironment.h"
class MyFeature : public pgtest::DbTest {};
TEST_F(MyFeature, Works)
{
REQUIRE_PG_AT_LEAST(15); // skip on older servers
auto r = conn().query("SELECT 1"); // Pgsql::Connection, throws on SQL error
EXPECT_EQ(r.rows(), 1);
}
```
- Derive from `pgtest::DbTest`. Each test gets a fresh database (`t_<n>_<pid>`) cloned from the template and dropped afterwards, so never rely on state from another test and freely modify data/schema.
- `conn()` is the test connection, `dbUrl()` gives a URL for code under test that opens its own connection (close those before the test ends; teardown uses `DROP DATABASE ... WITH (FORCE)`).
- Gate version-specific features with `REQUIRE_PG_AT_LEAST(v)`; use `pgtest::serverVersionNum()` for finer checks. Also test graceful behaviour on PG 14.
- `query()` throws on error; use `EXPECT_THROW` for expected failures.
## Adding things
- New test file: add it to the `add_executable(IntegrationTests ...)` list in `tests/integration/CMakeLists.txt` (no globbing).
- Shared schema: extend `tests/integration/fixtures/schema.sql` (plain multi-statement SQL, loaded once per process into the template). Keep it small; it must work on all of 14–17. Version-specific schema should be created inside the test.
- Cluster-wide objects (roles, tablespaces) are not isolated by cloning: use unique names (include `pgtest::processId()`) and drop them in `TearDown`.
## Running and checking
- One version manually: set `TEST_DATABASE_URL` and use `--gtest_filter` (see AGENTS.md); start servers with `docker compose -f tests/integration/docker-compose.yml up -d --wait pg16`, stop with `down -v`.
- After a run no `t_*` or `tmpl_*` databases should remain: `psql <url> -Atc "select datname from pg_database where datname ~ '^(t|tmpl)_'"`.