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

3 KiB
Raw Blame History

name description
pg-integration-tests 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

#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)_'".