![]() |
Massentests mit DUnitX
Schönen guten Tag zusammen,
ich bin gerade dabei mich in DUnitX einzuarbeiten und frage mich, ob es in diesem Test-Framework von Delphi möglich ist Massentests ohne ewig langen Code hinzubekommen. Beispiel: Ich habe eine Funktion vorliegen welche einfach nur 2 Werte, die als Eingangsparameter mitgegeben werden addieren soll: function TCalc.Add(x, y: Real): Real; begin Result := x + y; end; Und diese Funktion soll nun nicht mit "nur" 2 [TestCase] auf ihre Richtigkeit hin überprüft werden sondern mehrere Male.Ich stelle mir das etwa so vor: [Test] [TestCase('Add Test','0,0,0')] [TestCase('Add Test','0,1,1')] [TestCase('Add Test','0,2,2')] [TestCase('Add Test','0,3,3')] [TestCase('Add Test','0,4,4')] . . . . . [TestCase('Add Test','10,10,20')] procedure TestAdd(Value1, Value2, Expected: Real); Die Frage, die sich mir nun stellt ist: Wie ist es möglich (wie oben drüber dargestellt) so viele Testfälle darzustellen ohne diese explizit einzeln zu definieren? Kann man TestCases irgendwie durchloopen oder eine andere Möglichkeit sich bei "Massentests" im Code kurz zu halten? |
AW: Massentests mit DUnitX
Wie wäre es mit...
Delphi-Quellcode:
Und A und B kannst Du dann entsprechen vorgeben, errechnen.. was auch immer
begin
for I:=0 to 1000 do begin if Add(A,B) <> C then begin Assert.Fail; exit; end; end; Assert.Pass; end; |
AW: Massentests mit DUnitX
Der Nachteil bei dem Ansatz mit der for-Schleife ist, dass der Test beim ersten Fehler abbricht und Fehler in höheren Schleifendurchgängen erst entdeckt werden, wenn der Fehler behoben wurde. Aus diesem Grund wurden ja überhaupt dieses TestCase-Attribut erfunden.
Man kann das aber auch mit einem TestDataProvider lösen (hier zur Übersicht alles in einer Unit):
Delphi-Quellcode:
unit TestUnit1;
interface uses DUnitX.Types, DUnitX.InternalDataProvider, DUnitX.TestDataProvider, DUnitX.TestFramework; type TCalcSourceProvider = class(TTestDataProvider) private FMaxTest: Integer; public constructor Create; override; function GetCaseCount(const methodName: string): Integer; override; function GetCaseName(const methodName: string): string; override; function GetCaseParams(const methodName: string; const caseNumber: Integer): TValueArray; override; end; type [TestFixture] TCalcTestObject = class public [Test] [TestCaseProvider(TCalcSourceProvider)] // alternativ auch: [TestCaseProvider('CalcSourceProvider')] (siehe initialization) procedure TestAdd(Value1, Value2, Expected: Double); end; implementation constructor TCalcSourceProvider.Create; begin inherited; FMaxTest := 11*11; end; function TCalcSourceProvider.GetCaseCount(const methodName: string): Integer; begin Result := FMaxTest; end; function TCalcSourceProvider.GetCaseName(const methodName: string): string; begin Result := methodName; end; function TCalcSourceProvider.GetCaseParams(const methodName: string; const caseNumber: Integer): TValueArray; var A: Double; B: Double; begin A := caseNumber div 11; B := caseNumber mod 11; Result := TValueArray.Create(A, B, A + B); end; procedure TCalcTestObject.TestAdd(Value1, Value2, Expected: Double); begin { Hier testen wir erstmal, ob unser Dataprovider überhaupt funktioniert. Wenn das klappt, ersetzen wir das mit dem Test der TCalc-Methode Add } Assert.AreEqual(Expected, Value1 + Value2, 0.1); end; initialization TestDataProviderManager.RegisterProvider('CalcSourceProvider', TCalcSourceProvider); TDUnitX.RegisterTestFixture(TCalcTestObject); end. |
AW: Massentests mit DUnitX
Zitat:
D.h. dieser Schleifen-Ansatz hätte für die Veröffentliche SW-Version keinen Nachteil. Und diese Schleifenansatz hat den Vorteil das man eine großen Menge an Fällen testen kann. Das alles in tausenden Zeilen Attribute zu schreiben kostet nur zeit das zu schreiben. Der Attribut-Weg ist ja Fälle gedacht, in denen ich spezielle Werte testen will, aber nicht eine ganzen größeren Block. |
AW: Massentests mit DUnitX
Die Frage ist doch auch woher die Testdaten dann eigentlich kommen.
Eine vorgegebene Tabelle, empirische Daten, per Zufall, oder gibt es sogar eine Formel ? Ich bin prinzipiell etwas gegen vorgegebene Tabellen, denn damit ist meist die Idee des Testers verbunden, und seltene Fälle werden nie erkannt. |
AW: Massentests mit DUnitX
Uwe's Ansatz mit dem Provider finde ich richtig gut (+1) - kannte ich noch nicht - aber "meine" Schleife reicht mir in der Regel..
Wenn ein Unittest fehl schlägt, dann fixe ich diesen... Wenn mir Testinsight anzeigt das 1000 fehlgeschlagen sind, hilft mir das nicht weiter, sondern frustriert eher. I.d.R. fixed man doch einen Fehler nach dem anderen. Wobei ich keinen Sinn darin sehe 1+1 1+2 1+3 1+4 und so weiter zu testen... Das ist ein Computer, wenn er 1+1 rechnen kann, kann er auch 1+n rechnen. Es geht doch dann eher um die Corner-Cases... 1+0 1+-1 1+65568 1+0.5 oder was auch immer... Mavarik :coder: |
AW: Massentests mit DUnitX
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:
Der Witz ist aber, dass in den schlimmen Fällen der Code nur für eine bestimmte Kombination fehlschlägt. Das ist weitaus hilfreicher als wenn der Test mit der Schleife einfach nur fehlschlägt. Wenn du nämlich dann noch eine genaue Fehlermeldung ausgeben willst, mit welchen Werten das fehlgeschlagen ist, musste wieder unnötigen Code schreiben. Leider benamt DUnitX die Tests, die über den TestDataProvider erzeugt werden ein bisschen lame - mit meiner Implementierung in Spring.Testing siehst du genau, mit welchen Werten der Test aufgerufen wurde. Ein Beispiel, wie man sehr einfach Mengen von werten in einen Unittest stopfen kann, hab ich ![]() Ich kann dann genau den Test anhaken, der da fehlschlägt, und debuggen, ohne erst durch irgendne Schleife zu müssen und nen conditional Breakpoint zu setzen, der erst stoppt wenn der Wert kommt, der den Test fehlschlagen lässt, alles mühsamer Mist. Im übrigen ist der Ansatz, die Testdaten von extern zu bekommen gar nicht mal so abwegig, das nennt sich dann zum Beispiel "data driven testing" - da kann man tolle Sachen mit machen - natürlich in ganz anderem Ausmaße und nicht um nen Taschenrechner zu testen - obwohl, eigentlich braucht man fürn Taschenrechner bloß eine Testfunktion, die dann als Input die Formel hereinbekommt, die man eingetippt hat und das erwartete Ergebnis - und das kann man hervorragend in einer Textdatei oder so pflegen. |
AW: Massentests mit DUnitX
Zitat:
Zitat:
|
AW: Massentests mit DUnitX
Zitat:
|
AW: Massentests mit DUnitX
Zitat:
Da macht es dann sinn möglich einen großen Teil der möglichen Input/Output-Kombinationen zu prüfen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:29 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