Hallo zusammen,
wollte mal fragen wie ihr Testdaten für Integrationstests erstellt?
Ich meine jetzt speziell Integrationstests die auf Service Ebene (bzw. DAO/Repository Ebene) arbeiten, die brauchen ja bestimmte Daten um zu funktionieren.
Generell fallen mir da ein paar Möglichkeiten ein, haben alle ihre Vor- und Nachteile:
-
Man nimmt die DAOs selber um Testdaten zu erzeugen.
Vorteil: Man hat den Code schon.
Nachteil: Die DAOs sind ja teil des zu testenden Systems, man ist naturgemäss eingeschränkt was die Verifikation betrifft. Mappingfehler können schnell übersehen werden bzw. sind schwer zu finden, weil zB. das falsche Mapping von einem Objekt Feld auf ein Tabellenfeld sowohl beim schreiben als auch beim lesen verwendet wird, d.h. man merkt diese Art Fehler gar nicht.
Wenn man nun in bestimmten DAOs keine Methoden hat um zB. Daten anzulegen orer zu löschen weil die Fachlichkeit das nicht braucht, wirds problematisch, führt oft dazu dass diese Methoden, die nur von Tests genutzt werden, im Produktivcode enden. -
Man nimmt ein Framework wie DBUnit, SetupDB, etc. pp. kann ausser Daten einfügen auch direkt in der DB prüfen ob Werte richtig angekommen sind bzw. richtig gelesen wurden.
Vorteil: Man kann besser verifizieren, d.h. Mappingfehler sind einfach zu finden.
Nachteil: Man muss den Code schreiben, inkl. der Mappinginformationen zwischen Objekten und Tabellen, hat also zumindest die Mappinginformationen und DB Schema informationen redundant, einmal in Prod Code, dann nochmal im Testcode. -
SQL Files die einmal vor den Test eingespielt werden.
Vorteil: Man bekommt halt Daten in die DB zum testen, können zB. auf einer DB ausgelesen werden die schon “richtige” Daten enthält.
Nachteil: Die Mappingformationen sind auch hier redundant, wenn man die SQL file nicht manuell erstellt macht das nix. Allerdings ist es eher schwierig pro Testcase die sog. “minimale Fixture” einzuspielen, wird meist nur einmal für alle Test gemacht -> “Shared Fxiture”, d.h. Test werden wahrscheinlich interagieren (zB. ein Test verändert Daten der Shared Fixture um die Create/Update/Delete Methode des Services/DAOs zu testen, der nächste Test der die ursprüngliche Daten erwartet wird fehlschlagen wenn er nach den Test läuft die diese Daten verändern), oder die Test sind eher oberflächlich. -
Tests erzeugen Daten die von anderen Test als Testfixture verwendet werden
Nachteile: Abhängigkeiten zwischen Test, schlechte “defect localization”, nicht parallelisierbar, bei mehrmaligem Ausführen kann sich der Fehler “verändern”.
Persönlich bin ich ein Fan von DBUnit, trotz der Nachteile der zu schreibenden Codes und der redundanten Mapping Infos. Ersteres lohnt sich schnell wenn man die Builder verwendet (aufwändig zu schreiben, minimaler aufwand beim nutzen der Builder), letzteres lässt sich gut in den Griff bekommen wenn man dafür sorgt dass diese Mappinginformationen wirklich nur einmal Redundant gehalten werden.
Aber was mir wirklich wichtig ist, dass es Builder gibt die einem das erstellen der Testdaten für einen einzelnen Testcase so einfach macht, dass es keine Ausreden mehr gibt warum man keine sauberen Integrationstest schreibt (jeder Testcase erzeugt seine eigenen, einzigartigen Testdaten die in keinen anderen Test so vorkommen).
Factories für Testdaten (ObjetMother etc.) haben den Nachteil, dass die inflexibler sind als das Builder Pattern, funzen nur gut bei simplen Testdaten/Strukturen.
Die einzelnen Builder zu implementieren ist recht aufwändig, sie zu verwenden aber sehr einfach und kurz, man gibt nur noch Werte an die relevant für den Test sind, die anderen werden nicht von mir gesetzt sondern der Builder nimmt einfach Defaultwerte.
Wie macht ihr das so in euren Projekten?
Wie genau nimmt man es da mit Testen allgemein, Differenzierung zwischen Unittests und Integrationstest?
Vor allem: Wie bekommt ihr eure Testdaten in die DB??