Testing
Perseid uses two testing frameworks:
boost::ut is used for the unit tests, which construct objects in memory and verify SQL output without connecting to a database.
Catch2 is used for integration tests, which connect to an actual PostgreSQL database and verify end-to-end behavior.
Running the tests
cmake --build build
ctest --test-dir build
ctest runs the unit tests first and then the integration suite. The
integration suite requires PostgreSQL running locally.
createdb perseid_test
createdb perseid_test_src
Most suites share the perseid_test database. The functional
migration tests use perseid_test_src as its source database and
perseid_test as its target. Every database-backed test starts by
dropping all user schemas (including the public schema that
createdb creates), cascading to the objects they contain, so each
test observes an identical, empty database regardless of what earlier
runs left behind.
The database names are configurable, so the tests can run against
differently named databases. The integration and functional suites
read the PERSEID_TEST_DB and PERSEID_TEST_DB_SRC (functional only)
environment variables, defaulting to perseid_test and
perseid_test_src respectively when unset.
Smoke test: running against alternate databases
To verify that the environment-variable override works properly, you can create two throwaway databases, run the whole suite against them, then drop them:
createdb perseid_alt
createdb perseid_alt_src
PERSEID_TEST_DB=perseid_alt PERSEID_TEST_DB_SRC=perseid_alt_src \
ctest --test-dir build
dropdb perseid_alt
dropdb perseid_alt_src
The databases need no preparation beyond createdb; the tests reset
them on their own.
Unit tests
The unit tests live in src/dbobject and use boost::ut. They are
registered with CTest as test_schema, test_column,
test_constraint, and test_table.
# Run all unit tests
ctest --test-dir build -R "test_schema|test_column|test_constraint|test_table"
# Run a single unit test
ctest --test-dir build -R test_schema
# Or run a unit test binary directly
./build/src/dbobject/schema_test
Integration tests
The integration tests live in tests/ and use Catch2. They connect to
the test database through Rel_db: connection and statement-execution
tests verify execute/fetchone/commit/rollback semantics, and
table tests create an isolated schema (reldb_test_schema) to
exercise table loading and tuple queries end-to-end.
# Ensure the test database exists
createdb perseid_test
# Run all integration tests
ctest --test-dir build -R "_integration"
# Run specific integration suites
ctest --test-dir build -R test_reldb_integration
ctest --test-dir build -R test_schema_integration
ctest --test-dir build -R test_table_integration
ctest --test-dir build -R test_column_integration
ctest --test-dir build -R test_constraint_integration
# Or run binaries directly (with optional filters)
./build/tests/reldb_integration
./build/tests/reldb_integration "commit persists writes"
Functional tests
The functional tests are ports of Pyrseas’ functional test suite. The
first one, test_filmversions, executes SQL scripts against a source
database to build successive schema versions (0.1, 0.2, 0.3), mirrors
each version into a target database by applying the differences
between the two YAML descriptions, and after each step—and after
reverting to each earlier version—verifies that the two databases
are identical by diffing pg_dump output and YAML files. It uses the
Db_migrate_testcase base class from tests/testutils.cppm.
# Run the functional test
ctest --test-dir build -R test_filmversions
# Or run the binary directly (optionally with Catch2 tags or filters)
./build/tests/test_filmversions
./build/tests/test_filmversions "[film]"
In addition to both test databases, the test requires pg_dump and
diff to be available on PATH.
The SQL scripts live in tests/scripts/, separate from the test
sources. Temporary files (dumps, YAML and generated SQL) are written
to a perseid_test directory under the system temporary directory.
The directory is emptied at the start of each test run.
The suites share the same databases and temporary files, so test
executables should not be run concurrently; CTest runs them serially by
default. Note also that test_filmversions does not match the
_integration pattern, so it is not included in ctest -R "_integration".
Test organization
File |
Framework |
Coverage |
|---|---|---|
|
boost::ut |
Schema create/drop/diff (unit) |
|
boost::ut |
Column add/alter/drop (unit) |
|
boost::ut |
FK, PK, check, unique constraints (unit) |
|
boost::ut |
Table create/drop/diff, topo sort (unit) |
|
Catch2 |
Schema integration against live DB |
|
Catch2 |
Table integration against live DB |
|
Catch2 |
Column integration against live DB |
|
Catch2 |
Constraint integration against live DB |
|
Catch2 |
Rel_db integration (connection/execute/fetch/txn) |
|
Catch2 |
Functional test: film schema version migration and reversion |