Follow Us on Twitter

Unit testing met utPLSQL

geautomatiseerd testen
Gepubliceerd in

April 2005 - Een unit test is een geprogrammeerde test die door de ontwikkelaar zelfgeschreven wordt om de functionele werking van zijn code te valideren. Een unittest geeft uitsluitend goed of fout terug. Dit maakt ze uitermate geschikt om op een consistente manier het gedrag van de code te testen en om je ervan te verzekeren dat dit gedrag hetzelfde blijft tijdens het gehele ontwikkelproces.

In de Java/J2EE community wordt al veelvuldig gebruik gemaakt van unit tests. Op dit moment is jUnit de defacto standaard voor unit testing binnen Javaprojecten. Als naast Java/J2EE ook Oracle ingezet wordt, dan is het zeer waarschijnlijk dat er binnen de applicatie ook gebruik wordt gemaakt van stored procedures (triggers, procedures, functies of packages). Het is wenselijk om deze code ook te kunnen unit testen. Het is mogelijk om zelf daarvoor een framework te bouwen, maar het is ook mogelijk om daarvoor utPLSQL in te zetten,een open source framework voor unit testing van PL/SQL code. utPLSQL is ontworpen en ontwikkeld door Steven Feuerstein, als auteur van meerdere Oracle boeken zeker geen onbekende in de PL/SQL wereld.

In dit Whitebook zullen we bekijken hoe PL/SQL unit tests opgezet kunnen wordenen hoe utPLSQL daarin ondersteuning geeft. Op het moment van schrijven is de laatste versie van utPLSQL 2.1.1, alhoewel versie 2.2 op dit moment in beta is.Het is nog onduidelijk wanneer deze versie gereleased zal worden.

Voorbeeldcode

Om de werking van unit testing met utPLSQL toe te lichten zal in dit Whitebook gebruik gemaakt worden van een klein voorbeeldpackage, "STR". Dit package bevat twee functies, nl. "VERWISSEL" en "SORTEER". De source code voor deze package is in een ZIP-file te downloaden (zie onderaan deze Whitebook).

create or replace package str
  is
      
     function verwissel(
       p_str      in varchar2
     ,  p_pos1   in pls_integer default 0
     ,  p_pos2   in pls_integer default 0
     )
     return varchar2;

     function sorteer(
        p_str in varchar2
     )
     return varchar2;

  end; 

De functie VERWISSEL verwisselt twee karakters van positie binnen een string en de functie SORTEER sorteert alle karakters binnen een string. Nu zullen we gaan kijken hoe we deze package kunnen testen met behulp van utPLSQL.

Tests ontwerpen en implementeren

utPLSQL kan procedures, functies en packages in de database testen. Hiervoor gebruikt utPLSQL eigen packages. De naam van die packages begint standaard met'UT_.' De code om de package 'STR' te testen komt dan ook in een package'UT_STR'. Deze package moet standaard 2 procedures bevatten: UT_SETUP en UT_TEARDOWN.De setup-procedure moet ervoor zorgen dat eventuele data die de unit tests nodig hebben klaargezet wordt, de teardown-procedure zorgt er vervolgens weervoor dat alles in de oorspronkelijke staat teruggebracht wordt (bv. droppen van tabellen of een rollback). In het geval van het STR package is het niet nodig om data-structuren klaar te zetten, omdat het om simpele functies gaat.

Vervolgens bevat dit test-package een procedure voor elke te testen procedure of functie. In dit geval dus UT_VERWISSEL en UT_SORTEER.

De package specificatie ziet er dan zo uit:

create or replace package ut_str
  is
     procedure ut_setup;
     procedure ut_teardown;

     procedure ut_sorteer;
     procedure ut_verwissel;

  end ut_str; 

Binnen de body moeten vervolgens de echte unit tests gedefinieerd worden. Dit is een belangrijke stap, want het resultaat van de tests moet voldoende vertrouwen in de kwaliteit van de code geven! Het is dus zaak om voor elke mogelijke situatie een unit test te schrijven, zodat het gedrag onder alle omstandigheden voorspelbaar is.

Voor de functie SORTEER kunnen bijvoorbeeld de volgende situaties uitgewerkt worden:

Omschrijving Input Verwacht resultaat
Letters acb abc
Cijfers 4251 1245
Letters en cijfers a52b1c4 1245abc

Deze situaties worden als volgt opgenomen in de implementatie van UT_SORTEER:

procedure ut_sorteer is
     begin
        utassert.eq(
           'Letters'
        ,  str.sorteer('acb')
        ,  'abc'
        );

        utassert.eq(
           'Cijfers'
        ,  str.sorteer('4251')
       ,  '1245'
        );
        
        utassert.eq(
           'Letters en cijfers'
        ,  str.sorteer('a52b1c4')
        ,  '1245abc'
        );
     end ut_sorteer;
 

Het utAssert package verzet feitelijk het echte werk binnen het utPLSQLframework. Het bevat een flinke selectie aan vergelijkingsprocedures. In dit voorbeeld is alleen gebruik gemaakt van string-vergelijkingen, maar er zijn ook procedures die bijvoorbeeld de inhoud van tabellen kunnen controleren(utAssert.eqtable), de resultaten van queries (utAssert.eqquery) en of databaseobjecten al dan niet bestaan (utAssert.objexists vs. utAssert.objnotexists).

De implementatie van de VERWISSEL-functie kan bekeken worden in de source codebij deze Whitebook.

Tests uitvoeren

Om alle unit tests uit te voeren moet de volgende procedure gestart worden:

exec utplsql.test('STR');

wat dan hopelijk het volgende resultaat geeft:

>    SSSS   U     U   CCC     CCC   EEEEEEE   SSSS     SSSS
> S S U U C C C C E S S S S
> S U U C C C C E S S
> S U U C C E S S
> SSSS U U C C EEEE SSSS SSSS
> S U U C C E S S
> S U U C C C C E S S
> S S U U C C C C E S S S S
> SSSS UUU CCC CCC EEEEEEE SSSS SSSS
.
SUCCESS: "STR"

utPLSQL rapporteert dat alle unit tests zijn geslaagd, wat ons hopelijk voldoende vertrouwen geeft dat de SORTEER-functie doet wat hij moet doen.

Bugfixing met utPLSQL

Stel dat bovenstaande package in gebruik genomen wordt, maar op een zeker moment wordt een bug aangemeld: een gebruiker heeft opgemerkt dat een string gesorteerd wordt als 'FGadr', terwijl dat volgens hem duidelijk 'adFGr' zoumoeten zijn.

Het is verleidelijk om in die situatie gelijk de code in te duiken om het probleem te verhelpen, zo heel moeilijk ziet het er tenslotte niet uit. Toch is het beter om de oplossing van dit probleem om te draaien: schrijf eerst een unit test die het falende gedrag bevestigt, fix daarna de bug, en verifieer of de bug opgelost is door nogmaals de tests uit te voeren. Dit verzekert je ervan dat ook in de toekomst het gedrag van de functie SORTEER gewaarborgd blijft.

We breiden de functie UT_SORTEER als volgt uit:

utassert.eq(
          'Hoofdletters en kleine letters'
       ,  str.sorteer('FGadr')
       ,  'adFGr'
       );

Als we de test opnieuw uitvoeren, faalt deze met de volgende boodschap:

FAILURE - STR.UT_SORTEER: EQ "Hoofdletters en kleine letters" 
    Expected "adFGr" and got "FGadr"

Als we de code van de package STR vervolgens aanpassen om niet hoofdlettergevoelig te sorteren en de test daarna opnieuw uitvoeren, blijkt gelukkig dat alle tests weer slagen en dat deze bug opgelost is. De code kan weer ingechecked worden en bij de volgende uitrol naar productie kan deze bug als afgehandeld beschouwd worden.

utPLSQL binnen Java-projecten

Binnen een ontwikkelteam kan gebruik gemaakt worden van een buildserver, die bijvoorbeeld 's nachts alle tests uitvoert, de applicatie compileert en de resultaten daarvan naar alle ontwikkelaars stuurt. De stukken software die inzo'n geautomatiseerd build-proces gebruikt worden zijn bijvoorbeeld CVS, Ant enMaven. utPLSQL kan ook goed geïntegreerd worden in een dergelijke opzet,zodat ook de PL/SQL code binnen een project gedekt wordt door een frequenteunit test.

utPLSQL binnen een Oracle-project

Ook pure PL/SQL projecten kunnen profiteren van de mogelijkheden van utPLSQL.Als er geen Java-kennis aanwezig is, is het ook mogelijk om de unit testsgeautomatiseerd vanuit een database job uit te voeren en resultaten naar bv.een tabel weg te schrijven.

Veel bedrijven maken nog gebruik van Oracle Designer al dan nietin combinatie met CDM RuleFrame voor applicatie-ontwikkeling. Packages diedoor CDM RuleFrame gegenereerd zijn, bevatten functies die een business rulevalideren. Het is zeer goed mogelijk om deze CAPI's met utPLSQL te testen. Voorafworden dan alle functionele eisen vertaald naar unit tests. Vanwege de hoge mate vanstandaardisatie binnen CDM RuleFrame is het gemakkelijk om na het genereren tevalideren of de business rule implementaties voldoen aan de gestelde functionele eisen.

Conclusie

utPLSQL kan goed ingezet worden om bestaande of nog te ontwikkelen PL/SQL codete testen. Het verbetert de overall kwaliteit van de code en ook in de onderhoudsfase bewijst het zijn nut door resultaatgericht bugfixen mogelijk temaken. Alhoewel unit testing een principe uit de Java-wereld is, blijkt het ook goed toepasbaar op PL/SQL code. Het maakt daarbij niet uit of PL/SQL slechts een deel van het geheel is naast andere technologiën zoals Java, of dat er uitsluitend met Oracle gewerkt wordt.

Referenties

 

Over de auteur
Martin Schapendonk is een all-round Oracle en Java ontwikkelaar en adviseur. Martin heeft zich gespecialiseerd in de ontwikkeling van (web) applicaties met OraclePortal, (mod) PL/SQL en Java. Daarnaast houdt hij zich o.a. bezig met ontwikkelingen als utPLSQL, HTMLDB en Nagios.

Waardering:
 

Reacties

Nieuwe reactie inzenden

De inhoud van dit veld is privé en zal niet openbaar worden gemaakt.

Meer informatie over formaatmogelijkheden

CAPTCHA
Deze vraag is om te testen of u een persoon bent en om spam te voorkomen
Image CAPTCHA
Enter the characters shown in the image.