Test decorator: OneTimeSetup/OneTimeTearDown

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Benutzeravatar
Maddias
Lazarusforum e. V.
Beiträge: 22
Registriert: Mo 29. Apr 2019, 09:28
OS, Lazarus, FPC: Windows 10, Lazarus 2.2.6, FPC 3.2.2
Wohnort: Randwick, NSW, Australien
Kontaktdaten:

Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von Maddias »

Liebe Lazarus-Community,

ich gehe meine ersten Schritte mit Lazarus & FreePASCAL und habe mir als erste Aufgabe die Portierung eines DUnit-Projekts von Delphi vorgenommen (siehe auch hier).

In der Online Hilfe von fpcunit fand ich den Hinweis, wie man einen Test Decorator verwendet, um einmalige Setup & TearDown Methoden für alle Testfälle auszuführen (siehe auch hier). Ich habe mich strikt an das Beispiel gehalten und folgende Test Registrierung vorgenommen:

Code: Alles auswählen

 
initialization
  RegisterTestDecorator(TWorkLogTestSetup, TTestdmoEmployee);
end.
 


wobei die Klasse TWorkLogTestSetup folgende Methoden implementiert:

Code: Alles auswählen

 
procedure TWorkLogTestSetup.OneTimeSetup;
begin
  dmoMain := TdmoMain.Create(nil);
  dmoTestHelper := TdmoTestHelper.Create(nil);
  dmoTestHelper.CreateFixture;
end;
 
procedure TWorkLogTestSetup.OneTimeTearDown;
begin
  dmoTestHelper.Free;
  dmoMain.Free;
end;
 


Mein Problem ist das diese Methoden nicht ausgeführt werden sonder stattdessen die Testfälle von TTestdmoEmployee direkt ausgeführt werden, was zur Folge hat das es weder eine TdmoMain noch ein TdmoTestHelper Instanz gibt. Dadurch funktioniert mein Datenbank-Zugriff (TdmoMain) nicht und der Test Helper (TdmoTestHelper) kann kein Fixture generieren.

Was mache ich falsch?

Salut,
Mathias

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von fliegermichl »

Ohne diese Klassen zu kennen mal so geraten:

Sind die genannten Methoden in der Basisklasse evtl. als virtual deklariert?
In dem Fall musst du bei der Delarationb in der ableitenden Klasse "override" hinter die Methodebdefinition schreiben.

Gruß
Michael

Benutzeravatar
Maddias
Lazarusforum e. V.
Beiträge: 22
Registriert: Mo 29. Apr 2019, 09:28
OS, Lazarus, FPC: Windows 10, Lazarus 2.2.6, FPC 3.2.2
Wohnort: Randwick, NSW, Australien
Kontaktdaten:

Re: Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von Maddias »

Hallo Michael,

recht herzlichen Dank für Deine flotte Antwort.

Ja die Methoden TWorkLogTestSetup.OneTimeSetup & TWorkLogTestSetup.OneTimeTearDown sind als override deklariert. Gerade so wie im Beispiel hier gezeigt. Der TGuiTestRunner zeigt auch All Tests & TTestdmoEmployee an. Aber die einmaligen Setup & TearDown Methoden von TWorkLogTestSetup werden nicht ausgeführt. Woran liegt das?

download/file.php?mode=view&id=4842

Salut,
Mathias
Dateianhänge
TestSetup-Decorator.PNG
TestSetup-Decorator.PNG (11.09 KiB) 2585 mal betrachtet

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von m.fuchs »

Seltsam, also bei meinen Tests funktioniert es. Kannst du mal die komplette Unit deines Testcases posten?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
Maddias
Lazarusforum e. V.
Beiträge: 22
Registriert: Mo 29. Apr 2019, 09:28
OS, Lazarus, FPC: Windows 10, Lazarus 2.2.6, FPC 3.2.2
Wohnort: Randwick, NSW, Australien
Kontaktdaten:

Re: Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von Maddias »

Hallo m.fuchs,

recht herzlichen Dank für Deine Antwort. Ich habe meinen bisherigen Lazarus Source Code in ein ZIP ARchiv gepackt und dann auf meinen Web Server hochgeladen. Du Kannst es von hier herunterladen.

Im Endausbau habe ich mehrere Datenmodule, die ich über den Test Decorator mit dem Framework Registrieren möchte. Für den Moment reicht mir eine Testklasse. Später braucht es dann die Übersetzung für folgenden Delphi DUnit Code:

Code: Alles auswählen

 
initialization
  RegisterTest(
    TWorkLogTestSetup.Create(
      TTestSuite.Create('WorkLog Client/Server Tests',
        [TTestdmoEmployee.Suite,
         TTestdmoLookup.Suite,
         TTestfraEmployee.Suite,
         TTestfraLookup.Suite])));
end.
 

Testfälle für Formulare & Frames (z.B. TTestfraEmployee) scheinen ja nicht zum Funktionsumfang von fpcunit zu gehören. Die kann man sich "wegdenken". Funktioniert auch in Delphi nicht wirklich. Ich hatte sie bei meinem Vortrag einfach mal erwähnt aber auch gleich ihre Limitationen genannt.

Recht herzlichen Dank für eine kurze Antwort im Voraus.

Salut,
Mathias

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von m.fuchs »

Hab das gerade mal bei mir gestartet und Breakpoints in TWorkLogTestSetup.OneTimeSetup; und TWorkLogTestSetup.OneTimeTearDown gesetzt. Sie werden beide so ausgeführt wie es sein soll.
Ich habe jetzt erstmal den Quellcode in den ganzen Methoden und Testmethoden auskommentiert, da mir auch der passende Datenbanktreiber fehlt. Aber an den OneTime-Methoden liegt es erstmal nicht.
Ich schaue es mir nachher nochmal genauer an.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
Maddias
Lazarusforum e. V.
Beiträge: 22
Registriert: Mo 29. Apr 2019, 09:28
OS, Lazarus, FPC: Windows 10, Lazarus 2.2.6, FPC 3.2.2
Wohnort: Randwick, NSW, Australien
Kontaktdaten:

Re: Test decorator: OneTimeSetup/OneTimeTearDown

Beitrag von Maddias »

Liebe Forums-Teilnehmer,
lieber Michael,

recht herzlichen Dank für das tolle Wochenende in Wittenberg und Euer Feedback zu meinen Unit Testing Fragen.

Ich habe das Test Projekt nochmal vereinfacht und hier hochgeladen.

Das Problem ist das ein einzelner Testfall nicht dazu führt das alle Parent Testfälle auch ausgeführt werden. Hier der kritische Code von

Code: Alles auswählen

procedure TGUITestRunner.ActRunHighlightedTestExecute(Sender: TObject);
begin
  FFirstFailure := nil;
  if (TestTree.Selected <> nil) and (TestTree.Selected.Data <> nil) then
  begin
    testSuite := TTest(TestTree.Selected.Data);
  end;
  RunTest(testSuite);
  TestTree.MakeSelectionVisible;
end;

Es wählt nur den selektierten Knoten/Testfall aus. In DUnit sieht die Funktion so aus:

Code: Alles auswählen

procedure TGUITestRunner.RunSelectedTestActionExecute(Sender: TObject);
begin
  Setup;
  ListSelectedTests;
  ProgressBar.Max := 1;
  ScoreBar.Max    := 1;
  RunTheTest(Suite);
  {$IFDEF VER130}
    FreeAndNil(FSelectedTests);
  {$ELSE}
    FSelectedTests.Free;
    FSelectedTests := nil;
  {$ENDIF}
end;

mit der Methode ListSelectedTests:

Code: Alles auswählen

procedure TGUITestRunner.ListSelectedTests;
var
  aTest: ITest;
  aNode: TTreeNode;
begin
  FSelectedTests.Free;
  FSelectedTests := nil;
  FSelectedTests := TInterfaceList.Create;
 
  aNode := TestTree.Selected;
 
  while Assigned(aNode) do
  begin
    aTest := NodeToTest(aNode);
    FSelectedTests.Add(aTest as ITest);
    aNode := aNode.Parent;
  end;
end;

Diesem Code kann man entnehmen, daß alle Parent Nodes auch mit übergeben werden müssen als selektierte Testfälle, selbst dann wenn der Parent kein Testfall ist sondern nur eine Test Klasse oder ein Dekorator.

Eine Sache wäre noch echt wünschenswert: Alle fehlgeschlagenen Testfälle sollten auf einen Schlag selektierbar sein und alle erfolgreichen Testfälle deselektiert. DUnit löst das so:

Code: Alles auswählen

procedure TGUITestRunner.SelectFailedActionExecute(Sender: TObject);
var
  i: integer;
  ANode: TTreeNode;
begin
  { deselect all }
  ApplyToTests(TestTree.Items[0], DisableTest);
 
  { select failed }
  for i := 0 to FailureListView.Items.Count - 1 do
  begin
    ANode := TTreeNode(FailureListView.Items[i].Data);
    SetNodeState(ANode, true);
  end;
  UpdateStatus(True);
end;


Wenn ich bei der Überarbeitung mithelfen kann, laß es mich bitte wissen.

Salut,
Mathias

Antworten