Vorige week zijn we begonnen met een Oracle project waarin we voor het testen van onze plsql-code gebruik gaan maken van een unittest framework, genaamd utplsql.
Nu was ik even aan het spelen met het gedrag van ut_setup en ut_teardown om vast te stellen of het gedrag hetzelfde is als in het JUnit framework voor Java, waar utplsql van is afgeleid.
Wanneer met JUnit een TestCase wordt uitgevoerd waarin een setUp() en tearDown() en twee testmethodes (bijvoorbeeld testOne() en testTwo()) zijn gespecificeerd, dan zal het JUnit framework de methoden als volgt aanroepen:
Heel logisch, want je wilt voor elke test die je specificeert exact dezelfde beginsituatie hebben die je in je setUp opstelt. Bijvoorbeeld een set records die je in een dummytabel plaatst en na je test weer netjes verwijdert. Op deze manier zijn je verschillende testmethoden binnen een testcase niet afhankelijk van elkaar.
Nu heb ik in utplsql exact hetzelfde voorbeeld aangemaakt, waarin ik in een testpackage een ut_setup, een ut_teardown en twee testprocedures (ut_testOne en ut_testTwo) heb gespecificeerd.
Tot mijn verbazing bleek het gedrag als volgt te zijn:
Stel dat ik in mijn setup een bestand klaarzet in een directory waarop een procedure die ik wil testen op los gelaten worden. In ut_testOne laat ik de procedure los op de file met bepaalde parameters en na de bewerking wil ik een assert equal uitvoeren over de gemuteerde file en een reeds aangemaakte file zoals ik het had verwacht.
Vervolgens wordt testTwo uitgevoerd die de procedure loslaat op het bestand met andere parameters dan in testOne. Ook hier wordt een mutatie uitgevoerd in het bestand die ik vervolgens wil vergelijken met een bestand zoals ik had verwacht zoals die eruit zal zien na uitvoering van procedure2.
Echter, het bestand is al door testOne gemuteerd waardoor testTwo totaal in de soep loopt. De twee tests zijn dus afhankelijk van elkaar geworden, wat IMHO nooit mag gebeuren bij unittesting.
Over voorgaande heb ik twee vragen:
1: Is Unittesting een standaard afspraak hoe tests uitgevoerd worden, of dit nou in Java, C++, PL/SQL of Delphi wordt toegepast? Als dit inderdaad zo is, dan zou ik zeggen dat utplsql de standaarden heeft geschonden.
2: Klopt het dat de reden van setup en teardown niets anders is dan dat je voor elke gespecificeerde testmethode/procedure dezelfde beginsituatie hebt? Ik geloof namelijk dat de manier zoals utplsql omgaat met de setup en teardown totaal zijn doel voorbij schiet.
Nu was ik even aan het spelen met het gedrag van ut_setup en ut_teardown om vast te stellen of het gedrag hetzelfde is als in het JUnit framework voor Java, waar utplsql van is afgeleid.
Wanneer met JUnit een TestCase wordt uitgevoerd waarin een setUp() en tearDown() en twee testmethodes (bijvoorbeeld testOne() en testTwo()) zijn gespecificeerd, dan zal het JUnit framework de methoden als volgt aanroepen:
code:
1
2
3
4
5
6
| setUp() testOne() tearDown() setUp() testTwo() tearDown() |
Heel logisch, want je wilt voor elke test die je specificeert exact dezelfde beginsituatie hebben die je in je setUp opstelt. Bijvoorbeeld een set records die je in een dummytabel plaatst en na je test weer netjes verwijdert. Op deze manier zijn je verschillende testmethoden binnen een testcase niet afhankelijk van elkaar.
Nu heb ik in utplsql exact hetzelfde voorbeeld aangemaakt, waarin ik in een testpackage een ut_setup, een ut_teardown en twee testprocedures (ut_testOne en ut_testTwo) heb gespecificeerd.
Tot mijn verbazing bleek het gedrag als volgt te zijn:
code:
1
2
3
4
| ut_setup ut_testOne ut_testTwo ut_teardown |
Stel dat ik in mijn setup een bestand klaarzet in een directory waarop een procedure die ik wil testen op los gelaten worden. In ut_testOne laat ik de procedure los op de file met bepaalde parameters en na de bewerking wil ik een assert equal uitvoeren over de gemuteerde file en een reeds aangemaakte file zoals ik het had verwacht.
Vervolgens wordt testTwo uitgevoerd die de procedure loslaat op het bestand met andere parameters dan in testOne. Ook hier wordt een mutatie uitgevoerd in het bestand die ik vervolgens wil vergelijken met een bestand zoals ik had verwacht zoals die eruit zal zien na uitvoering van procedure2.
Echter, het bestand is al door testOne gemuteerd waardoor testTwo totaal in de soep loopt. De twee tests zijn dus afhankelijk van elkaar geworden, wat IMHO nooit mag gebeuren bij unittesting.
Over voorgaande heb ik twee vragen:
1: Is Unittesting een standaard afspraak hoe tests uitgevoerd worden, of dit nou in Java, C++, PL/SQL of Delphi wordt toegepast? Als dit inderdaad zo is, dan zou ik zeggen dat utplsql de standaarden heeft geschonden.
2: Klopt het dat de reden van setup en teardown niets anders is dan dat je voor elke gespecificeerde testmethode/procedure dezelfde beginsituatie hebt? Ik geloof namelijk dat de manier zoals utplsql omgaat met de setup en teardown totaal zijn doel voorbij schiet.