CPPUnit

Wenn man ein C++-Programm geschrieben hat und es kompiliert kann man es einfach ausprobieren, um es zu testen. Der Nachteil solcher manueller Tests ist, dass sie prinzipiel nach jedem Compilerlauf neu ausgeführt werden müssten.

Sobald ein Programm mehrere Funktionen anbietet, steigt der Testaufwand entsprechend. Dies ist durch einen Benutzer schnell nicht mehr zu leisten. Also müssen Tests automatisiert werden.

Der erste Schritt ist dabei kleine Einheiten 1) zu finden, die man einzeln testen kann. Diese Einheiten sind in C++ in der Regel in Klassen gekapselt. Nehmen wir als Beispiel eine ganz einfache Klasse Stack:

class Stack
{
  unsigned int * Buffer;
  unsigned int   Size;
  unsigned int   Position; 
 
  public:
    Stack( unsigned int size );
    ~Stack();
 
    bool Push( unsigned int   value );
    bool Pop ( unsigned int & value );
 
    inline unsigned int * GetBuffer() { return Buffer; }
    inline unsigned int   GetSize()   { return Size; }
    inline unsigned int   GetUsed()   { return Position; }  
};

Nun kann man eine Oberfläche schreiben, um Werte auf den Stack zu pushen und sich anschließend den Stack anschauen. Auch wenn man mit einem Stack nicht viel anstellen kann, nämlich Werte aufladen und wieder vom Stack nehmen, so müssen auch die Werte von getUsed() und getSize() geprüft werden. Was passiert, wenn man mehr Werte auf den Stack „pusht“, als der Stack groß ist? Was passiert, wenn man mehr Werte abruft, als auf dem Stack liegen?

All dies muss geprüft werden und zwar immer dann, sobald sich irgendwo etwas geändert, das in irgendeiner Form mit dem Stack zu tun hat oder auch nur haben könnte.

Um das zu ermöglichen, automatisiert man diese Tests.

Ein guter Testprogrammierer testet also die Grundfunktion mehrfach ab und sucht also die möglichen Schwachstellen und vergleicht die Werte mit den Werten, die man erwartet. Beim Stack wird also zusätzlich der Überlauf getestet und das Abrufen von Werten bei einem leeren Stack.

Man schreibt also ein Programm, dass einen Stack erstellt, füllt und prüft, ob der Stack enthält, was man erwartet.

Eine sogenannte Test-Suite enthält so schnell dutzende oder hunderte Tests. Hierbei geht es nicht darum Methoden wie getSize() zu testen, sondern das Zusammenspiel von Methoden in einem bestimmtem Ablauf. So muss getUsed() 1 zurückliefern, nachdem man Push einmalig aufgerufen hat. In einem anderen Test, bei dem aus einem leeren Stack ein Wert abgerufen wird, erwarten wir als Rückgabe von Pop den Wert false als Zeichen des Fehlschlags, aber dabei darf getUsed() anschließend weiterhin 0 sein. Gibt getUsed() einen anderen Wert zurück, ist dieses Ergebnis nicht erwartet und auch nicht erwünscht: Ein Fehler wurde gefunden.

Um diese Tests zu verwalten hilft CPP-Unit.

1)
engl. Units