[alg/oo] testen van database apps

Pagina: 1
Acties:
  • 188 views sinds 30-01-2008
  • Reageer

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Ik wil me eens goed gaan verdiepen in het testen van applicaties. Ik heb al hier en daar wat gelezen over unit testen en test driven development ed. maar ik heb er toch nog wat problemen mee. Ik heb mijn app netjes ingedeelt in verschillende lagen, waarbij ik bij het testen me uiteraard vooral op de domain model laag wil richten (de laag dus waar alle core app/business logica in verwerkt zit in de vorm van objecten die een weerspiegeling zijn van het probleem domein).

Het probleem is dat veel acties eindigen in het update van de database op wat voor manier dan ook. Hoe gaan jullie hier mee om tijdens het testen? Mogelijkheden die ik zou kunnen bedenken zijn om bij iedere test eerst (automatisch) een lege (of gedeeltelijk gevulde) db voor te breiden, waarna de test wordt uitgevoerd en waarop je dan de inhoud van de database controleerd of dit wel overeenkomt met wat de bedoeling was. Een 2de is om voor het wegschrijven helemaal geen acties op de database uit te voeren, maar om ipv. van de objecten die dat verzorgen gewoon stubs/mocks te gebruiken die de acties reporten en de aangeleverde objecten op hun waarden controleren oid.

Wat is nu de beste methode en hoe is jullie ervaring hiermee?

Ik heb de Data Access code vrij los zitten van de domein code, ik roep wel functies op objecten daaruit aan, maar dat doe ik via een object welke een interface gedefinieerd in de domein laag implementeerd en die via een soort van depency injection wordt aangeleverd. Het maken van een stub dus lukt me dus wel.

Noushka's Magnificent Dream | Unity


  • momania
  • Registratie: Mei 2000
  • Laatst online: 19:39

momania

iPhone 30! Bam!

Ik zorg meestal voor een script dat voor initiele load zorgt van de database.
En daarbij per test suite en/of test case een script om voor die test(en) nog eventuele data aan te passen in de database.

Daar omheen heb ik dan nog een script dat de huidige situatie uit de database exporteerd en na het draaien van de unit testen weer restored.

Zo heb je tijdens het draaien van je testen altijd dezelfde uitgangs situatie en hou je ook je orginele situatie in tact.

Testen met stubs vind ik alleen handig als je een deel van de applicatie vanuit je ontwikkel omgeving echt niet kan benaderen. (dus de database of een bepaalde service, andere applicatie, etc).
Het kost nml. vaak toch wel erg veel tijd om een stub te schrijven omdat ze bijna niet generiek op te zeten zijn in de meeste gevallen.

Neem je whisky mee, is het te weinig... *zucht*


Verwijderd

Michali schreef op dinsdag 19 juli 2005 @ 21:33:
Het probleem is dat veel acties eindigen in het update van de database op wat voor manier dan ook.
Misschien sla ik de plank mis voor jouw situatie...
maar hou er wel rekening mee dat je je business logica methods zoveel mogelijk op zichzelf laat staan. Dat ze dus niet verweven worden met de stukken code waarin je data transporteert tussen lagen of objecten bijvoorbeeld.
Dat vergemakkelijkt het testen al een beetje.
... bij iedere test eerst (automatisch) een lege (of gedeeltelijk gevulde) db voor te breiden, waarna de test wordt uitgevoerd en waarop je dan de inhoud van de database controleerd of dit wel overeenkomt met wat de bedoeling was.
Dit lijkt me een prima oplossing.
Een 2de is om voor het wegschrijven helemaal geen acties op de database uit te voeren, maar om ipv. van de objecten die dat verzorgen gewoon stubs/mocks te gebruiken die de acties reporten en de aangeleverde objecten op hun waarden controleren oid.
Dan ga je misschien je testsysteem teveel af laten wijken van de productie versie. En als dat zo is, zou ik er niet voor kiezen.

  • The Eagle
  • Registratie: Januari 2002
  • Laatst online: 21:29

The Eagle

I wear my sunglasses at night

Waar heb je zelf al gezocht om naar verschillende testmethodes te kijken en vergelijken :? Lijkt me dat er op internet toch best wel het e.e.a. te vinden moet zijn. Denk aan zaken als TMAP, maar er zin ook nog wel andere methodes. Kwestie van de goede zoekstrings ingeven lijkt me :)

Al is het nieuws nog zo slecht, het wordt leuker als je het op zijn Brabants zegt :)


  • KurtDB
  • Registratie: Juni 2004
  • Laatst online: 09-02 20:28
Het gaat hier weliswaar wel over hibernate mappings testen, maar 't principe is toch hetzelfde: http://www.theserverside..../UnitTesting/article.html

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Je moet eens kijken naar hoe (komt ie weer) Ruby On Rails het doet. Ze gebruiken daar ook Unit Testing. Je hebt in rails standaard drie databases: een voor de ontwikkeling, een voor de live-site en een voor het testen. Er wordt ook altijd aangeraden om vooral niet overal dezelfde database voor te gebruiken, aangezien Unit-tests dingen met je database kunnen doen... Je kan natuurlijk mock-objects gebruiken, maar vaak werkt een extra database toch een stuk fijner. En het gaat inderdaad op de manier die jij ook voorstelde: je vult de database met wat initial records, gaat je unit tests doen en vervolgens is je database een grote rotzooi :p

  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Je moet m.i. gewoon een testdatabase opzetten. Het lijkt me nogal suf om te zeggen: "De queries schakel ik uit, want ik ga er vanuit dat daar 0 fouten in zitten." Ook de database-access moet je testen.

Je business-layer kan nog zo goed zijn; wanneer je database zich in een inconsistente toestand bevindt ben je alsnog fucked.

Siditamentis astuentis pactum.


  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 22-04 03:55

Nick_S

++?????++ Out of Cheese Error

Je kunt ook eens kijken naar DBUnit, een JUnit extensie speciaal voor database testing zonder database, zodat je bij elke testrun dezelfde data hierin hebt staan.

Ff wat linkjes spammen:
http://dbunit.sourceforge.net/
http://www.onjava.com/pub/a/onjava/2004/01/21/dbunit.html

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Het leek me zelf ook al niet zo'n goed idee om wat stubs op te gaan zetten voor het testen. Ook daar kunnen natuurlijk fouten in gaan zitten (ook omdat het vervelend werk ik natuurlijk). Ik ga dan idd voor een oplossing met het testen met een echte db (niet een live versie natuurlijk). Ik was toch benieuwd naar hoe de mensen het hier allemaal doen, een paar extra meningen over een bepaald onderwerp is niet verkeerd imo.

Noushka's Magnificent Dream | Unity


Verwijderd

Michali schreef op dinsdag 19 juli 2005 @ 21:33:
Mogelijkheden die ik zou kunnen bedenken zijn om bij iedere test eerst (automatisch) een lege (of gedeeltelijk gevulde) db voor te breiden, waarna de test wordt uitgevoerd en waarop je dan de inhoud van de database controleerd of dit wel overeenkomt met wat de bedoeling was.
Maar wat je hier feitelijk doet is de werking van je database server testen en niet de werking van je code. Mock je dao objecten en test of ze in de correcte volgorde met correcte argumenten worden aangeroepen :)

Verwijderd

Nick_S schreef op woensdag 20 juli 2005 @ 10:09:
Je kunt ook eens kijken naar DBUnit, een JUnit extensie speciaal voor database testing zonder database, zodat je bij elke testrun dezelfde data hierin hebt staan.

Ff wat linkjes spammen:
http://dbunit.sourceforge.net/
http://www.onjava.com/pub/a/onjava/2004/01/21/dbunit.html
Ik gebruik zelf ook DBUnit en ben daar best tevreden over. In principe is het idee dat je wat test data als XML bestanden in je project dir neerzet. DBUnit heeft zelf functies om vanaf een query die test data uit je originele DB te halen en meteen naar XML te saven.

Voordat een test begint kun je de test(!) DB laten leeghalen, vullen met de test data (vanaf het XML bestand dus), je functies executen, en optioneel de DB weer leeg laten maken. Het voordeel is dat je altijd met een known state test en niet afhankelijk bent van toevaligheden.

Je kunt in je test functies dus gewoon hard aannames doen. Stom voorbeeld: stel je hebt een functie die column X van table Y opvraagt en alle waardes bij elkaar optelt. Jij weet aan de hand van de known test data dat daar bijvoorbeeld 98 uit moet komen. Je kunt dus gewoon een testSUM() schrijven met een assert dat je result 98 is.

Voorderest zitten er handige functies in om tables met elkaar te vergelijken. Probleem is wel een beetje de volgorde van rijen, maar als je table sortable is kun je dat oplossen. Niet ter zake doende colommen kun je optioneel uit je vergelijking weglaten.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Verwijderd schreef op woensdag 20 juli 2005 @ 12:28:
[...]
Maar wat je hier feitelijk doet is de werking van je database server testen en niet de werking van je code. Mock je dao objecten en test of ze in de correcte volgorde met correcte argumenten worden aangeroepen :)
Maar het is (in mijn geval) zo dat bij bepaalde acties (vrijwel alle) een of andere vorm van database interactie komt kijken. Sowieso worden er objecten uit de db getrokken en moeten ze soms weer opgeslagen worden. Uiteraard kan dat gefaked worden met stubs, maar ik kom er niet omheen dat er een of enkele functies in de data access layer worden aangeroepen. Het maken van stubs lijkt me overigens geen voordeel hebben boven het maken van een test db. In dit geval zit ik er zelfs aan te denken om speciale decorators te maken voor de objecten die verantwoordelijk zijn voor het mappen en om dan de aangeroepen methodes te rapporteren bij de test case. Dan kan ik er toch relatief gemakkelijk achter komen of de functies wel in de juiste volgorde zijn aangeroepen en of de juiste parameters zijn aangeleverd.

[ Voor 4% gewijzigd door Michali op 21-07-2005 12:12 ]

Noushka's Magnificent Dream | Unity


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Soms wil je je unit test applicatie door een klant laten uitvoeren omdat deze een probleem heeft waar jij van wil weten waar dit precies zit. Daarom moet een test applicatie ook op een productie database kunnen worden uitgevoerd lijkt mij? Het is dus de verantwoordelijkheid van de unit tests dat deze al hun zooi correct opruimen.

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Michali schreef op donderdag 21 juli 2005 @ 12:10:
Maar het is (in mijn geval) zo dat bij bepaalde acties (vrijwel alle) een of andere vorm van database interactie komt kijken.
bingo, en dat wil je dus niet in elke test meenemen, want dan test je bij elke test je database en dat is uiteraard niet wenselijk. Dat je ergens je database test lijkt me logisch, maar dat zal niet veel voorstellen (een paar inserts/updates of whatever). Wat je niet moet doen is businesslogica in combinatie met je db gaan testen, dat is onzinnig omdat je immers weet dat die paar updates en insert al werken. Daarom kun je beter gewoon je dao's mocken zodat je enkel controleert of je create en update methodes worden aangeroepen. Op dat moment ben je je code aan het testen en niet de werking van je database :)

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Verwijderd schreef op donderdag 21 juli 2005 @ 15:10:
[...]
bingo, en dat wil je dus niet in elke test meenemen, want dan test je bij elke test je database en dat is uiteraard niet wenselijk. Dat je ergens je database test lijkt me logisch, maar dat zal niet veel voorstellen (een paar inserts/updates of whatever). Wat je niet moet doen is businesslogica in combinatie met je db gaan testen, dat is onzinnig omdat je immers weet dat die paar updates en insert al werken. Daarom kun je beter gewoon je dao's mocken zodat je enkel controleert of je create en update methodes worden aangeroepen. Op dat moment ben je je code aan het testen en niet de werking van je database :)
Goed punt idd. Dan lijkt het me toch een betere methode. Maar als ik van die mock tegelijkertijd een decorator maak (die dus alle calls wel doorstuurt naar het 'echte' object), dan kan ik gelijk beide testen. Of is dat geen goed plan?

Noushka's Magnificent Dream | Unity


Verwijderd

Ik vind van niet aangezien ik het liefst de testen strict gescheiden houd. Als een test faalt weet je waar je het zoeken moet en vooral waar je het niet zoeken moet. Tevens lopen je tests een stuk sneller als je enkel losse onderdeeltjes test. Als je immers bezig bent met het ontwikkelen van businesslogica hoef je tijdens een test niet je database test te draaien wat gewoon een stukje tijd scheelt.

Verwijderd

Als je met DB mock objecten je business logic -kunt- testen, houdt dat meestal tevens in dat je indien nodig makkelijk naar een andere storage kunt overstappen. Mes snijdt aan 2 kanten.
Pagina: 1