![]() |
Unittest von OnWhatever Events?
Hallo Zusammen!
Wie mache ich ein Unittest von einem OnWhatever Event? Beispiel:
Delphi-Quellcode:
Wie bringe ich das hier unter, dass ich:
procedure TestIUDFDatenbank.TestInit;
var ClientGUID: TGUID; begin // TODO: Methodenaufrufparameter einrichten FIUDFDatenbank.Init(ClientGUID); // Wenn der InitThread fertig ist wird ein Event OnInitDone aufgerufen // TODO: Methodenergebnisse prüfen end; 1. Testen kann ob innerhalb von 10 Sekunden der OnInitDone aufgerufen wurde 2. Oder der OnInitFailure Mavarik |
AW: Unittest von OnWhatever Events?
Ich gehe mal davon aus, daß die Events innerhalb des Init-Aufrufs ausgeführt werden. Dann kannst du die Events auf entsprechende Methoden des TestCase setzen, die eine Feld im TestCase setzen, daß du dann nach dem Init prüfst.
Die Zeit kannst du testen, indem du dir den Start von Init merkst und in den jeweiligen Events das Intervall abprüfst. Für nicht-synchrone Events ist DUnit allerdings gar nicht gut geeignet. |
AW: Unittest von OnWhatever Events?
Zitat:
Zitat:
Die Init läuft in einem Thread und feuert irgendwann den OnXXXX. Kommt also sofort wieder. Ich müsste also im TestCase eigentlich einen Anonymen Thread starten der auf das Ergebnis warten kann (5 Sekunden oder was auch immer) um in der Testcase procedure dann true oder false zu erzeugen. Richig???? |
AW: Unittest von OnWhatever Events?
Zitat:
Pseudocode:
Delphi-Quellcode:
Edit: Du solltest den Event in gar keinem Thread starten. Das ist ja kein Integrationstest, der die 'Blackbox' (Thread und Objekt) testet, sondern nur das Abfeuern des Events.
// Arrange
unitUnderTest := TMyObject.Create; unitUnderTest.OnEvent := TestEvent; StartTime := Now; EventWasFired := False; EventTime := 0; // Act unitUnderTest.TriggerTheEvent(); // This is nonworking pseudocode but you should get the point WaitUntil (EventWasFired or (Now-StartTime > maxTimeToWait)); // Assert Assert.That(EventWasFired , 'The Event was not called'); Assert.That(EventTime-StartTime <= TenSeconds, 'The Event was not called in Time'); ... Procedure TTestCase.TestEvent(Sender : TObject); Begin EventTime := Now; EventWasFired := True; End; |
AW: Unittest von OnWhatever Events?
Zitat:
|
AW: Unittest von OnWhatever Events?
Beides, oder?
1. Teste den Thread, das er das macht, was er machen soll (z.B. die Objektmethode aufrufen, die einen Event feuern soll. Ob der gefeuert wird, interessiert den Thread ja nicht). 2. Teste das Objekt, das den Event feuert, wenn es soll. |
AW: Unittest von OnWhatever Events?
Zitat:
Beim Unittest darf man eben nie aus den Augen verlieren, was man testen möchte. Manchmal benötigt man auch ein paar Dummies zum Testen, denn wer will schon beim Testen einer SEPA-Schnittstelle aus Versehen 100000,00€ überweisen oder per Lastschrift einziehen. ;) |
AW: Unittest von OnWhatever Events?
Hatte vor einiger Zeit schonmal was in DSharp für async/await in Delphi zusammen gebaut, was mir hier in abgewandelter Form nützlich erschien:
Delphi-Quellcode:
unit Unit1;
interface uses MyDings, SyncObjs, TestFramework; type TDingsTest = class(TTestCase) private fSUT: TMyDings; fInitDoneEvent: TEvent; procedure HandleInitDone(Sender: TObject); protected procedure SetUp; override; procedure TearDown; override; published procedure OnInitDone_Is_Fired_Within_Ten_Seconds_After_Calling_Init; end; implementation uses Classes, Diagnostics, Forms, Math, Windows; function WaitFor(handle: THandle; timeout: Cardinal): TWaitResult; var handles: array[0..1] of THandle; stopwatch: TStopwatch; begin if GetCurrentThreadId = MainThreadID then begin handles[0] := handle; handles[1] := SyncEvent; stopwatch := TStopwatch.StartNew; repeat case MsgWaitForMultipleObjects(2, handles, False, IfThen(timeout = INFINITE, INFINITE, timeout - stopwatch.ElapsedMilliseconds), QS_ALLINPUT) of WAIT_OBJECT_0: Exit(wrSignaled); WAIT_OBJECT_0 + 1: CheckSynchronize; WAIT_OBJECT_0 + 2: Application.ProcessMessages; WAIT_ABANDONED: Exit(wrAbandoned); WAIT_FAILED: Exit(wrError); end; until stopwatch.ElapsedMilliseconds >= timeout; Result := wrTimeout; end else case WaitForSingleObject(handle, timeout) of WAIT_OBJECT_0: Result := wrSignaled; WAIT_ABANDONED: Result := wrAbandoned; WAIT_TIMEOUT: Result := wrTimeout; else Result := wrError; end; end; { TDingsTest } procedure TDingsTest.HandleInitDone(Sender: TObject); begin fInitDoneEvent.SetEvent; end; procedure TDingsTest.OnInitDone_Is_Fired_Within_Ten_Seconds_After_Calling_Init; begin fSUT.Init; CheckTrue(WaitFor(fInitDoneEvent.Handle, 10000) = wrSignaled); end; procedure TDingsTest.Setup; begin fSUT := TMyDings.Create; fSUT.OnInitDone := HandleInitDone; fInitDoneEvent := TEvent.Create; end; procedure TDingsTest.Teardown; begin fInitDoneEvent.Free; fSUT.Free; end; initialization RegisterTest(TDingsTest.Suite); end. |
AW: Unittest von OnWhatever Events?
Ja das sieht gut aus, Danke!
Muss mir nur noch überlegen, wie und ob ich den produktiven Teil des Init abkoppele oder mit testen soll... Ich möchte ja ggf. nicht nur die Funktionalität der Procedure Testen, sondern ggf. auf die Daten die hinten raus kommen. Vielleicht muss ich da noch ein Dummy-Interface mit übergeben, welches die Routinen von der aktiven Datenbank auf ein Testmodel umlenkt.. (Siehe SEPA Beispiel) Jeremy North hatte da so ein schönes Kreditkartenbeispiel... Aber ich denke so komme ich erst mal weiter... Mavarik |
AW: Unittest von OnWhatever Events?
Gibt es eine "elegante" Möglichkeit innerhalb des Testforms an zu zeigen, das ein Test noch läuft und nicht abgestürzt ist?
Mavarik |
AW: Unittest von OnWhatever Events?
Zitat:
Alles andere würd ja irgendwie entweder das Timeout signalisieren oder ne Exception werfen. |
AW: Unittest von OnWhatever Events?
Zitat:
kann natürlich ein Fester aufmachen... Bitte warten... Nicht alle Testroutinen sind in 2 Sekunden fertig... Was ist wenn ein Test 2 Minuten dauert? Mavarik |
AW: Unittest von OnWhatever Events?
Zitat:
In Bezug auf die Zeit muss man sagen, direkte Unittests sollten so geschrieben werden, dass sie sehr schnell durchlaufen (gerade wenn man TDD macht). Aber mit DUnit kann man ja nicht nur Unittests sondern auch Integrationstest durchführen, die durchaus ihre Zeit in Anspruch nehmen können. Das wäre aber wohl dann was, was man in den DUnit GUIRunner einbauen könnte. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz