# 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 ```bash 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. ```bash 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: ```bash 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`. ```bash # 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. ```bash # 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`. ```bash # 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 | |------|-----------|----------| | `src/dbobject/schema_test.cpp` | boost::ut | Schema create/drop/diff (unit) | | `src/dbobject/column_test.cpp` | boost::ut | Column add/alter/drop (unit) | | `src/dbobject/constraint_test.cpp` | boost::ut | FK, PK, check, unique constraints (unit) | | `src/dbobject/table_test.cpp` | boost::ut | Table create/drop/diff, topo sort (unit) | | `tests/test_schema.cpp` | Catch2 | Schema integration against live DB | | `tests/test_table.cpp` | Catch2 | Table integration against live DB | | `tests/test_column.cpp` | Catch2 | Column integration against live DB | | `tests/test_constraint.cpp` | Catch2 | Constraint integration against live DB | | `tests/test_reldb.cpp` | Catch2 | Rel_db integration (connection/execute/fetch/txn) | | `tests/test_filmversions.cpp` | Catch2 | Functional test: film schema version migration and reversion |