Integrationstests von C++ mit Docker: Von A bis Z
\n\nIntegrationstests sind eine entscheidende Phase in der Entwicklung jedes ernsthaften C++-Projekts. Sie ermöglichen es zu überprüfen, wie einzelne Module des Systems zusammenarbeiten, mit Datenbanken, Netzwerkdiensten und Dateisystemen interagieren. Docker wird in diesem Zusammenhang zu einem unverzichtbaren Werkzeug: Es bietet eine isolierte, reproduzierbare Umgebung und vermeidet Probleme mit "es funktioniert auf meinem Rechner". In diesem Artikel werden wir den gesamten Zyklus der Einrichtung von Integrationstests für C++ mit Docker durchgehen – von den grundlegenden Konzepten bis zu fortgeschrittenen Praktiken.
\n\n1. Warum Docker für Integrationstests von C++?
\n\nTraditionelle Integrationstests für C++ leiden oft unter Umgebungsproblemen: unterschiedliche Bibliotheksversionen, inkompatible Compiler, spezifische Betriebssystemeinstellungen. Docker löst diese Probleme ein für alle Mal. Die Hauptvorteile:
\n\n- \n
- Reproduzierbarkeit: Jeder Test wird in einer identischen Umgebung ausgeführt, unabhängig vom Host-System. \n
- Isolation: Container beeinflussen sich gegenseitig und das Host-System nicht. \n
- Skalierbarkeit: Hunderte von Tests können problemlos parallel ausgeführt werden. \n
- CI/CD-Integration: Container passen perfekt in Pipelines von Jenkins, GitLab CI, GitHub Actions. \n
Betrachten wir ein einfaches Beispiel: Ihre C++-Anwendung verwendet PostgreSQL. Ohne Docker müssten Sie PostgreSQL auf jedem Testserver installieren und konfigurieren. Mit Docker ist das eine einzige Konfigurationszeile.
\n\n2. Einrichtung der Docker-Umgebung für ein C++-Projekt
\n\nBeginnen wir mit der Erstellung eines Dockerfiles für unsere C++-Anwendung. Angenommen, das Projekt verwendet CMake und Google Test für Unit-Tests, aber wir benötigen Integrationstests mit einer echten Datenbank.
\n\nBasis-Dockerfile für Build und Tests:
\n\n# Dockerfile\nFROM ubuntu:22.04 AS builder\n\nRUN apt-get update && apt-get install -y \\\n build-essential \\\n cmake \\\n git \\\n libpq-dev \\\n libgtest-dev \\\n && rm -rf /var/lib/apt/lists/*\n\nWORKDIR /app\nCOPY . .\n\nRUN cmake -B build -DCMAKE_BUILD_TYPE=Release \\\n && cmake --build build --parallel\n\n# Stufe für Tests\nFROM builder AS tester\nCMD ["./build/integration_tests"]\n\nDocker Compose zum Starten der Infrastruktur:
\n\n# docker-compose.yml\nversion: '3.8'\n\nservices:\n db:\n image: postgres:15\n environment:\n POSTGRES_DB: testdb\n POSTGRES_USER: testuser\n POSTGRES_PASSWORD: testpass\n healthcheck:\n test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"]\n interval: 5s\n timeout: 5s\n retries: 5\n\n app:\n build: .\n depends_on:\n db:\n condition: service_healthy\n environment:\n DB_HOST: db\n DB_PORT: 5432\n DB_NAME: testdb\n DB_USER: testuser\n DB_PASSWORD: testpass\n command: ["./build/integration_tests"]\n\n3. Schreiben von Integrationstests in C++
\n\nBetrachten wir ein Beispiel für einen Integrationstest, der die Interaktion mit PostgreSQL über die Bibliothek libpqxx überprüft. Angenommen, wir haben ein Modul zur Benutzerverwaltung.
\n\nBeispiel für einen Integrationstest:
\n\n// integration_tests.cpp\n#include <gtest/gtest.h>\n#include <pqxx/pqxx>\n#include <string>\n#include <vector>\n\nclass DatabaseIntegrationTest : public ::testing::Test {\nprotected:\n void SetUp() override {\n conn = new pqxx::connection(\n "host=" + std::getenv("DB_HOST") +\n " port=" + std::getenv("DB_PORT") +\n " dbname=" + std::getenv("DB_NAME") +\n " user=" + std::getenv("DB_USER") +\n " password=" + std::getenv("DB_PASSWORD")\n );\n \n // Erstellen einer Testtabelle\n pqxx::work txn(*conn);\n txn.exec("CREATE TABLE IF NOT EXISTS use