44 lines
3 KiB
Markdown
44 lines
3 KiB
Markdown
|
|
---
|
|||
|
|
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)_'"`.
|