E2E-Tests von C++-Anwendungen: von der Theorie bis zum produktiven CI/CD

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

Warum „nur Unit-Tests“ nicht mehr ausreichen?

\n\n

Sie haben perfekten C++-Code geschrieben. Die Kompilierung war erfolgreich, die Unit-Tests sind grün, das Code-Review wurde genehmigt. Sie bringen ein Release heraus – und eine Stunde später beschweren sich die Benutzer: „Der Button funktioniert nicht“, „Die Datenbank antwortet nicht“, „Die GUI hängt“. Kommt Ihnen das bekannt vor?

\n\n

Das Problem ist, dass Unit-Tests eine Funktion prüfen, aber kein Szenario. Sie sind isoliert. In der realen Welt interagiert Ihr C++-Code jedoch mit dem Netzwerk, dem Dateisystem, der GPU, externen APIs und anderen Threads. Genau hier kommen E2E-Tests von C++-Anwendungen (End-to-End- oder durchgängige Tests) ins Spiel.

\n\n

In diesem Artikel werden wir uns ansehen, wie man das Chaos von Integrationsfehlern in ein strukturiertes System automatischer Überprüfungen verwandelt. Sie erfahren, welche Werkzeuge wirklich funktionieren, wie man Tests schreibt, die beim ersten Start nicht auseinanderfallen, und wie man E2E in die CI/CD-Pipeline integriert. Los geht's!

\n\n

Was ist E2E-Testing im Kontext von C++?

\n\n

E2E-Testing ist die Überprüfung eines vollständigen Benutzerszenarios „von Anfang bis Ende“. Im Gegensatz zu Modultests, die eine einzelne Funktion prüfen, startet ein E2E-Test Ihre Anwendung (oder einen kritischen Teil davon) in einer Umgebung, die der Produktion so nahe wie möglich kommt.

\n\n

Für C++ kann dies bedeuten:

\n
    \n
  • Desktop-Anwendung: Starten eines Fensters, Klicken auf die Schaltfläche „Senden“, Überprüfen, ob die Daten in der Datenbank gelandet sind.
  • \n
  • Serveranwendung: Senden einer HTTP-Anfrage an Ihre REST-API, Überprüfen der Antwort und des Datenbankzustands.
  • \n
  • Embedded/Software: Anlegen eines Signals am Eingang, Überprüfen des Ausgangssignals nach einer bestimmten Zeit.
  • \n
\n\n

Der entscheidende Unterschied ist die reale Umgebung. Keine Mock-Objekte für Datenbank oder Netzwerk. Nur echte Hardware (oder Docker).

\n\n

Werkzeugkasten: Was funktioniert 2024 wirklich für C++?

\n\n

Kommen wir direkt zur Sache. Hier ist der Stack, den wir im Einsatz verwenden:

\n\n
    \n
  • Catch2 oder Google Test – zum Schreiben der Teststruktur (Arrange-Act-Assert).
  • \n
  • Docker – zum Bereitstellen einer sauberen Umgebung (DB, Warteschlangen, Abhängigkeiten).
  • \n
  • Pytest + subprocess – zur Orchestrierung (ja, Python, aber es ist ideal zum Verkleben von C++-Binärdateien).
  • \n
  • Selenium/Appium – wenn Sie eine GUI mit Qt oder WebView haben.
  • \n
  • CMake + CTest – zum Ausführen von Tests und Sammeln von Ergebnissen.
  • \n
\n\n

Versuchen Sie nicht, E2E-Tests nur in C++ zu schreiben. Das ist schmerzhaft. Verwenden Sie Python als Kleber – es ist schneller für Integrationsszenarien.

\n\n

Praxis: Schreiben eines E2E-Tests für eine REST-API in C++

\n\n

Angenommen, wir haben einen C++-Server mit cpp-httplib (oder crow, oder drogon). Er akzeptiert POST-Anfragen unter /api/user und speichert den Benutzer in PostgreSQL.

\n\n

Schreiben wir einen E2E-Test, der:

\n
    \n
  1. Einen Docker-Container mit PostgreSQL hochfährt.
  2. \n
  3. Unseren Server kompiliert und startet.
  4. \n
  5. Eine HTTP-Anfrage über curl (oder einen C++-Client) sendet.
  6. \n
  7. Überprüft, ob der Benutzer in der Datenbank erscheint.
  8. \n
\n\n

Schritt 1: Docker-compose für die Testumgebung

\n\n
version: '3.8'\nservices:\n  db:\n    image: postgres:15\n    environment:\n      POSTGRES_DB: testdb\n      POSTGRES_USER: testuser\n      POSTGRES_PASSWORD: testpass\n    ports:\n      - "5432:5432"\n  app:\n    build: .\n    depends_on:\n      - db\n    ports:\n      - "8080:8080"\n    environment:\n      DB_HOST: db\n
\n\n

Schritt 2: Test in C++ mit Catch2

\n\n
// test_e2e_api.cpp\n#include <catch2/catch_test_macros.hpp>\n#include <httplib.h>\n#include <nlohmann/json.hpp>\n#include <cstdlib>\n\nTEST_CASE("E2E: Create user via API and verify in DB") {\n    // Arrange\n    httplib::Client cli("localhost", 8080);\n    nlohmann::json user = {\n        {"name", "John Doe"}                

Blogs

Buchempfehlungen