Testen in C++: Unit, Integration, E2E von A bis Z

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

Einleitung: Warum Testen in C++ kein Luxus, sondern eine Notwendigkeit ist



In der Welt von C++ ist Codequalität von entscheidender Bedeutung. Die Sprache gibt dem Entwickler enorme Kontrolle über Speicher und Leistung, aber diese Macht erfordert hohe Verantwortung. Ein Fehler im Speichermanagement, die falsche Verwendung von Zeigern oder eine fehlerhafte Arbeit mit Multithreading können zu schwer fassbaren Bugs führen, die sich erst in der Produktion zeigen.



Testen ist die einzige zuverlässige Methode, um sicherzustellen, dass Ihr C++-Code sich wie beabsichtigt verhält. In diesem Artikel gehen wir den Weg von kleinen Unit-Tests bis hin zu vollständigen End-to-End (E2E)-Prüfungen. Sie erfahren, wie Sie eine Teststrategie richtig aufbauen, welche Werkzeuge Sie verwenden und wie Sie Tests schreiben, die wirklich einen Nutzen bringen.



Wir betrachten drei Ebenen der Testpyramide: Unit (Modultests), Integration (Integrationstests) und E2E (End-to-End-Tests). Jede Ebene löst ihre eigene Aufgabe, und erst ihre Kombination gibt vollständige Sicherheit über die Zuverlässigkeit des Programms.



Unit-Testing: Das Fundament der Qualität



Unit-Tests sind die unterste und schnellste Ebene. Sie überprüfen einzelne Funktionen, Klassen oder Methoden in Isolation von externen Abhängigkeiten (Datenbanken, Dateisystem, Netzwerk). Das Hauptziel ist sicherzustellen, dass jede logische Einheit des Codes korrekt funktioniert.



Auswahl eines Frameworks für C++



Im C++-Ökosystem gibt es mehrere beliebte Frameworks für Unit-Tests:



  • Google Test (gtest) — das am weitesten verbreitete Framework von Google. Unterstützt Assertions, Fixtures, parametrisierte Tests und Mocks (über Google Mock).
  • Catch2 — ein leichtes und modernes Framework mit hervorragender Syntax. Besonders gut geeignet für schnelles Prototyping von Tests.
  • Boost.Test — Teil der Boost-Bibliothek. Leistungsstark, aber schwergewichtiger.


Für das Beispiel verwenden wir Google Test, da es in vielen C++-Projekten der De-facto-Standard ist.



Beispiel eines Unit-Tests in C++



Angenommen, wir haben eine einfache Funktion zur Berechnung der Fakultät:



// math_utils.h#ifndef MATH_UTILS_H#define MATH_UTILS_H

long long factorial(int n);

#endif

// math_utils.cpp#include "math_utils.h"

long long factorial(int n) { if (n < 0) throw std::invalid_argument("Negative input"); if (n == 0) return 1; long long result = 1; for (int i = 1; i <= n; ++i) { result *= i; } return result;}


Jetzt schreiben wir einen Unit-Test mit Google Test:



// test_math_utils.cpp#include <gtest/gtest.h>#include "math_utils.h"

TEST(FactorialTest, HandlesZeroInput) { EXPECT_EQ(factorial(0), 1);}

TEST(FactorialTest, HandlesPositiveInput) { EXPECT_EQ(factorial(1), 1); EXPECT_EQ(factorial(5), 120); EXPECT_EQ(factorial(10), 3628800);}

TEST(FactorialTest, ThrowsOnNegative) { EXPECT_THROW(factorial(-1), std::invalid_argument);}


Dieser Test überprüft drei Szenarien: den Grenzfall (0), die normale Funktionsweise und die Fehlerbehandlung. Beachten Sie die Makros EXPECT_EQ und EXPECT_THROW — sie unterbrechen den Test bei einem Fehler nicht, sondern protokollieren ihn lediglich.



Mock-Objekte zur Isolation



Für Unit-Tests ist es entscheidend, den zu testenden Code von externen Abhängigkeiten zu isolieren. Dazu werden Mock-Objekte verwendet. Google Mock (Teil von Google Test) ermöglicht es, einfach Stubs zu erstellen:



// database_connector.hclass DatabaseConnector {public:    virtual ~DatabaseConnector() = default;    virtual bool connect(const std::string& url) = 0;    virtual std::vector<int> fetchData() = 0;};

// user_service.cppclass UserService { DatabaseConnector& db;public: UserService(DatabaseConnector& db) : db(db) {} int ge

Blogs

Buchempfehlungen