Integrationstests für C++ mit Docker: Ein praktischer Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten
```html

Integrationstests für C++ mit Docker



Moderne C++-Entwicklung erfordert nicht nur das Schreiben von qualitativ hochwertigem Code, sondern auch die Sicherstellung seines zuverlässigen Betriebs unter realen Bedingungen. Integrationstests sind eine Schlüsselphase, die es ermöglicht, die Interaktion von Systemkomponenten zu überprüfen: Datenbanken, Netzwerkdienste, Dateisysteme. Die Verwendung von Docker für diese Zwecke bietet eine isolierte, reproduzierbare Umgebung, die sich ideal für CI/CD-Pipelines eignet. In diesem Artikel werden wir durchgehen, wie man Integrationstests für C++-Anwendungen mit Docker einrichtet, und praktische Beispiele liefern.



Warum Docker für C++-Integrationstests?



Traditionelle Ansätze für C++-Integrationstests stoßen oft auf Probleme:

  • Umgebungsabhängigkeit: Tests können auf dem Entwicklerrechner funktionieren, aber auf dem Build-Server aufgrund unterschiedlicher Bibliotheksversionen fehlschlagen.
  • Komplexität der Einrichtung: Für Tests mit einer echten Datenbank oder einer externen API ist eine manuelle Konfiguration erforderlich.
  • Paralleler Start: Mehrere Testläufe können aufgrund gemeinsamer Ressourcen in Konflikt geraten.

Docker löst diese Probleme, indem es leichte, isolierte Container bereitstellt. Sie können eine Testdatenbank hochfahren, Ihren C++-Dienst starten und die Tests ausführen – alles innerhalb einer einzigen docker-compose-Datei. Dies garantiert, dass die Umgebung auf jeder Maschine identisch ist.



Projekteinrichtung: Ein Basisbeispiel



Betrachten wir einen einfachen C++-Dienst, der Daten in PostgreSQL speichert. Für Integrationstests benötigen wir:

  • Den C++-Code selbst mit Tests (wir verwenden Google Test).
  • Ein Dockerfile zum Bauen und Ausführen der Tests.
  • Eine docker-compose.yml zur Orchestrierung der Container.


Projektstruktur:

my_cpp_project/├── src/│   ├── main.cpp│   ├── database.cpp│   └── database.h├── tests/│   └── test_integration.cpp├── CMakeLists.txt├── Dockerfile└── docker-compose.yml


Dockerfile:

FROM gcc:latest AS builder

WORKDIR /appCOPY . .

RUN apt-get update && apt-get install -y cmake libpq-devRUN cmake -B build -DCMAKE_BUILD_TYPE=ReleaseRUN cmake --build build

FROM ubuntu:22.04

RUN apt-get update && apt-get install -y libpq-devCOPY --from=builder /app/build/tests /app/testsCOPY --from=builder /app/build/my_app /app/my_app

ENTRYPOINT ["/app/tests"]


docker-compose.yml:

version: '3.8'services:  db:    image: postgres:15    environment:      POSTGRES_USER: testuser      POSTGRES_PASSWORD: testpass      POSTGRES_DB: testdb    ports:      - "5432:5432"    healthcheck:      test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"]      interval: 5s      timeout: 5s      retries: 5

test: build: . depends_on: db: condition: service_healthy environment: DB_HOST: db DB_PORT: 5432 DB_USER: testuser DB_PASSWORD: testpass DB_NAME: testdb


Schreiben von C++-Integrationstests



Jetzt erstellen wir einen Test, der das Schreiben und Lesen aus der Datenbank überprüft. Wir verwenden Google Test und die Bibliothek libpqxx für die Arbeit mit PostgreSQL.



tests/test_integration.cpp:

#include <gtest/gtest.h>#include <pqxx/pqxx>#include <string>

class DatabaseTest : public ::testing::Test {protected: void SetUp() override { conn = new pqxx::connection( "host=" + std::string(std::getenv("DB_HOST")) + " port=" + std::string(std::getenv("DB_PORT")) + " user=" + std::string(std::getenv("DB_USER")) + " password=" + std::string(std::getenv("DB_PASSWORD")) + " dbname=" + std::string(std::getenv("DB_NAME")) ); }

void TearDown() override { delete conn; }

pqxx::connection *conn;};

TEST_F(DatabaseTest, CanInsertAndRetrieveData) { pqxx::work txn(*conn); txn.exec("CREATE TABLE IF NOT EXISTS test_table (id SERIAL PRIMARY KEY, value TEXT)"); txn.exec("INSERT INTO test_table (value) VALUES ('Hello, Docker!')"); txn.commit();

pqxx::work txn2(*conn); pqxx::result result = txn2.exec("SELECT value FROM test_table WHERE value = 'Hello, Docker!'"); EXPECT_EQ(result.size(), 1); EXPECT_EQ(result[0][0].as(), "Hello, Docker!");}

Blogs

Buchempfehlungen