Unit-Tests in Delphi mit DUnit
Delphi enthält standardmäßig ab Version 2010 das Test-Framework DUnit. Dieses ist inspiriert vom JUnit-Framework und ermöglicht Unit-Testing auch unter Delphi. Für ältere Versionen der Delphi IDE ist das Framework auch unter http://dunit.sourceforge.net/ erhältlich.
Grundsätzlich sei gesagt, dass DUnit mittlerweile veraltet ist und nicht mehr weiter gewartet wird. Es gibt aber mit dem DUnitX-Framwork einen Nachfolger für DUnit, welcher in Delphi Versionen ab 2010 verwendet werden kann. Ältere Versionen werden allerdings nicht mehr unterstützt.
Vorerst wollen wir uns aber DUnit ansehen, da in unserer Version Delphi XE der Wizard zum Erstellen von Testklassen integriert ist. In einem weiteren Blog-Eintrag erkläre ich, wie der Umstieg auf DUnitX erfolgt.
Zuerst erstellen wir eine einfache Formularanwendung (VCL-Formularanwendung) mit einem Fenster, einem Button, ein paar Labels und SpinEdits:
Um die Addition durchzuführen, erstellen wir eine zusätzliche Unit welche eine Klasse namens TAddCalculation deklariert:
unit AddCalculator; interface type TAddCalculator = class(TObject) public constructor create; function getResult(number1, number2: integer): integer; private end; implementation constructor TAddCalculator.create; begin end; function TAddCalculator.getResult(number1, number2: integer): integer; begin result := number1 + number2; end; end.
Diese Klasse wird in unserer Form verwendet um die beiden eingegebenen Zahlen zu addieren:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Spin, AddCalculator; type TForm1 = class(TForm) Button1: TButton; LabelResult: TLabel; SpinEdit1: TSpinEdit; SpinEdit2: TSpinEdit; Label2: TLabel; Label3: TLabel; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private addCalculator: TAddCalculator; { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin labelResult.Caption := inttostr(addCalculator.getResult(SpinEdit1.value, SpinEdit2.value)); end; procedure TForm1.FormCreate(Sender: TObject); begin addCalculator := TAddCalculator.create; end; end.
Soweit ein einfacher Anwendungsfall. Nun wollen wir unsere TAddCalculator-Klasse testen, ob sie die Kalkulation auch immer ordnungsgemäß durchführt. Wir wollen also einen Unit-Test erstellen. Dazu geht man in Delphi unter „Datei“ -> „Neu“ -> „Weitere“ und wählt unter dem Folder Unit-Test die Erstellung eines neuen „Testprojekt“ aus:
Wir wählen unser Quellprojekt, geben den Namen unseres Test-Projektes an und fügen das Testprojekt unserer Projektgruppe hinzu. Dies hat den Vorteil, mit dem Öffnen unserer Projektgruppe sowohl die Anwendung als auch die Tests gleichzeitig zu öffnen.
Als Test-Runner wählen wir GUI:
Nachdem unser Test-Projekt angelegt ist, wollen wir unseren ersten Test anlegen. Hierzu gehen wir wieder auf „Datei“ -> „Neu“ -> „Weitere“, wählen diesmal unter dem Ordner „Unit-Test“ die Erstellung eines „Test-Fall“ aus. Im darauf folgenden Fenster geben wir die zu testende Quelldatei an und welche Methode wir testen wollen:
Mit dem Klick auf „Fertig stellen“ erstellt Delphi ein Skelett der Testklasse, welches wir für unsere Zwecke erweitern können:
unit TestAddCalculator; { Delphi DUnit-Testfall ---------------------- Diese Unit enthält ein Skeleton einer Testfallklasse, das vom Experten für Testfälle erzeugt wurde. Ändern Sie den erzeugten Code so, dass er die Methoden korrekt einrichtet und aus der getesteten Unit aufruft. } interface uses TestFramework, AddCalculator; type // Testmethoden für Klasse TAddCalculator TestTAddCalculator = class(TTestCase) strict private FAddCalculator: TAddCalculator; public procedure SetUp; override; procedure TearDown; override; published procedure TestgetResult; end; implementation procedure TestTAddCalculator.SetUp; begin FAddCalculator := TAddCalculator.Create; end; procedure TestTAddCalculator.TearDown; begin FAddCalculator.Free; FAddCalculator := nil; end; procedure TestTAddCalculator.TestgetResult; var ReturnValue: Integer; begin ReturnValue := FAddCalculator.getResult(2, 3); CheckEquals(5, ReturnValue); end; initialization // Alle Testfälle beim Testprogramm registrieren RegisterTest(TestTAddCalculator.Suite); end.
Entscheidend sind die 2 Zeilen 47/48:
ReturnValue := FAddCalculator.getResult(2, 3); CheckEquals(5, ReturnValue);
Hier rufen wir die Methode „getResult“ unserer zu testenden Klasse auf und überprüfen mithilfe der Funktion CheckEquals, ob das Ergebnis auch unserem erwarteten Resultat entspricht.
CheckEquals ist eine der Funktionen, die das DUnit-Framework zur Verfügung stellt. Es entspricht dem AssertEquals in Java. Daneben gibt es noch folgende Funktionen:
- CheckNotEquals: prüft, ob zwei Werte nicht gleich sind
- CheckTrue: prüft, ob ein Wert true ist
- CheckFalse: prüft, ob ein Wert false ist
- CheckNull: prüft, ob ein Wert nil ist
- CheckNotNull: prüft, ob ein Wert nicht nil ist
- CheckInherits: prüft, ob eine Klasse von einer anderen abgeleitet ist
- CheckIs: prüft, ob ein Objekt von einer bestimmten Klasse ist
- Fail: lässt den Test einfach fehlschlagen, führt selbst keine Prüfungen durch
Starten wir nun unseren Test, indem wir einfach auf den Ausführen-Button in Delphi klicken, erscheint ein Fenster in welchem wir die Tests starten können und das Ergebnis farblich präsentiert bekommen:
Um wieder unsere Beispielanwendung starten zu können, müssen wir nur in der Projektverwaltung ein Doppelklick auf diese durchführen, sodaß diese fett angezeigt wird. Ein weiterer Klick auf den Ausführen-Button startet nun wieder unsere Anwendung:
Schreibe einen Kommentar
Du musst angemeldet sein, um einen Kommentar abzugeben.