Add framework for executing tests against multiple postgresql versions using docker compose.

This commit is contained in:
eelke 2026-10-18 12:09:54 +02:00
parent 655c6fceb1
commit c3bf9e88e4
13 changed files with 457 additions and 0 deletions

View file

@ -0,0 +1,43 @@
add_executable(IntegrationTests
main.cpp
tst_Smoke.cpp
)
target_link_libraries(IntegrationTests PRIVATE
pgintegration
GTest::gtest
Qt6::Core
)
target_compile_definitions(IntegrationTests PRIVATE
PGTEST_FIXTURE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/fixtures"
)
set_target_properties(IntegrationTests PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
)
option(PGLAB_INTEGRATION_TESTS "Register Docker based PostgreSQL integration tests" OFF)
if (PGLAB_INTEGRATION_TESTS)
set(PGTEST_COMPOSE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/docker-compose.yml)
add_test(NAME db_up
COMMAND docker compose -f ${PGTEST_COMPOSE_FILE} up -d --wait)
add_test(NAME db_down
COMMAND docker compose -f ${PGTEST_COMPOSE_FILE} down -v)
set_tests_properties(db_up PROPERTIES FIXTURES_SETUP pgcluster LABELS integration)
set_tests_properties(db_down PROPERTIES FIXTURES_CLEANUP pgcluster LABELS integration)
foreach (v 14 15 16 17)
add_test(NAME integration_pg${v} COMMAND IntegrationTests)
set_tests_properties(integration_pg${v} PROPERTIES
FIXTURES_REQUIRED pgcluster
LABELS integration
ENVIRONMENT "TEST_DATABASE_URL=postgresql://postgres:test@localhost:543${v}/postgres")
endforeach ()
else ()
add_test(NAME IntegrationTests COMMAND IntegrationTests)
set_tests_properties(IntegrationTests PROPERTIES LABELS integration)
endif ()

View file

@ -0,0 +1,16 @@
x-pg: &pg
environment: { POSTGRES_PASSWORD: test }
tmpfs: [/var/lib/postgresql/data]
command: >
postgres -c fsync=off -c synchronous_commit=off
-c full_page_writes=off -c max_connections=200
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 1s
retries: 30
services:
pg14: { <<: *pg, image: "postgres:14", ports: ["54314:5432"] }
pg15: { <<: *pg, image: "postgres:15", ports: ["54315:5432"] }
pg16: { <<: *pg, image: "postgres:16", ports: ["54316:5432"] }
pg17: { <<: *pg, image: "postgres:17", ports: ["54317:5432"] }

View file

@ -0,0 +1,6 @@
CREATE TABLE fixture_item (
id integer PRIMARY KEY,
name text NOT NULL
);
INSERT INTO fixture_item (id, name) VALUES (1, 'one'), (2, 'two');

View file

@ -0,0 +1,10 @@
#include <gtest/gtest.h>
#include "PgTestEnvironment.h"
int main(int argc, char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
::testing::AddGlobalTestEnvironment(new pgtest::PgEnv(PGTEST_FIXTURE_DIR));
return RUN_ALL_TESTS();
}

View file

@ -0,0 +1,63 @@
#include "DbTest.h"
#include "PgTestEnvironment.h"
#include "Pgsql_Result.h"
using namespace pgtest;
namespace {
int scalarInt(Pgsql::Connection &c, const char *sql)
{
Pgsql::Result r = c.query(sql);
EXPECT_EQ(r.rows(), 1);
return QString::fromUtf8(r.val(0, 0)).toInt();
}
} // namespace
class Smoke : public DbTest {};
TEST_F(Smoke, SelectOne)
{
EXPECT_EQ(scalarInt(conn(), "SELECT 1"), 1);
}
TEST_F(Smoke, RunsOnClonedDatabase)
{
Pgsql::Result r = conn().query("SELECT current_database()");
ASSERT_EQ(r.rows(), 1);
EXPECT_EQ(QString::fromUtf8(r.val(0, 0)), dbName());
EXPECT_TRUE(dbName().startsWith("t_"));
}
TEST_F(Smoke, ServerVersionAtLeast14)
{
EXPECT_GE(serverVersionNum(), 140000);
}
TEST_F(Smoke, FixtureSchemaPresent)
{
EXPECT_EQ(scalarInt(conn(), "SELECT count(*) FROM fixture_item"), 2);
}
// The two tests below each modify the database and expect the pristine
// fixture state, in whichever order they run.
TEST_F(Smoke, IsolationA)
{
EXPECT_EQ(scalarInt(conn(), "SELECT count(*) FROM fixture_item"), 2);
conn().query("INSERT INTO fixture_item VALUES (100, 'a')");
EXPECT_EQ(scalarInt(conn(), "SELECT count(*) FROM fixture_item"), 3);
}
TEST_F(Smoke, IsolationB)
{
EXPECT_EQ(scalarInt(conn(), "SELECT count(*) FROM fixture_item"), 2);
conn().query("DELETE FROM fixture_item");
EXPECT_EQ(scalarInt(conn(), "SELECT count(*) FROM fixture_item"), 0);
}
TEST_F(Smoke, VersionGate)
{
REQUIRE_PG_AT_LEAST(15);
EXPECT_GE(serverVersionNum(), 150000);
}