• No results found

Hur kan databasen testas med hänsyn till dessa utmaningar?

A.7 Slutsatser

B.4.4 Hur kan databasen testas med hänsyn till dessa utmaningar?

Programmeringsspråk

Användningen av flera programmeringsspråk, kräver en noggrann testning av mappningen av data mellan dessa [53]. Denna testning kräver att applikationen och den underliggande databasen interagerar med varandra och görs rimligtvis med integrationstestning. Statisk testning är en god utgångspunkt, att säkerställa att datatyperna i tabeller är korrekta och att funktionerna i applikationen kan översättas till dessa. Vanligtvis hanteras själva översätt- ningen av ett API, exempelvis JDBC [54] i Java, men utvecklaren har fortfarande ansvaret att datatyper med en korrekt motsvarighet i databasen, skickas från applikationen. Vidare följer dynamisk testning, där det säkerställs att rätt värden lagras och hämtas vid exekvering av funktioner och att dessa värden mappar mot korrekta tabellfält i databasen [53]. Detta kräver förstås att dessa funktioner också mappar mot de rätta procedurerna i databasen, som utför de önskade operationena.

Databastillstånd

Då det är viktigt att känna till databasens tillstånd före och efter exekvering av tester, är det ett rimligt tillvägagångssätt att placera databasen i ett känt tillstånd inför testning [40]. Man

B.5. Diskussion

kan rimligtvis generera påhittat data, eller använda sig av data som databasen hade vid ett visst tillfälle under normal drift [40]. Används det senare alternativet, riskerar man att inte få tillräckligt med variation. Om databasen inte isoleras korrekt, riskerar man även datakorrup- tion [40]. Det mycket säkrare tillvägagångssättet är därför att i en isolerad testmiljö, använda påhittat data, som framställts helt i testningssyfte [40]. I teoriavsnittet ges förslag på koncep- tuella verktyg som ska underlätta framtagningen av testdata. I praktiken däremot, särskilt för mindre projekt, kan testdata och testfall framtas av en testansvarig, med god kunskap om databasens struktur [53].

Testning i praktiken

Christensen et al. [55] betonar vikten av att utvecklare i testsyfte, ska kunna sätta upp (set up) och riva ner (tear down) databaser på ett så effektivt sätt som möjligt. Det poängteras att populära testramverk som exempelvis JUnit [23], följer filosofin att enhetstester ska vara helt oberoende av varandra. Denna filosofi återspeglas också i extensioner till detta ramverk, ex- empelvis DbUnit [56], som är specialiserad för enhetstestning av databasapplikationer. En konsekvens av denna filosofi som lyfts fram av Christensen et al., är att det blir både tidskrä- vande och mycket repetition av kod. Detta kan förstås vara acceptabelt för vissa applika- tioner, men då det kommer till just databasapplikationer, innebär det att behöva initialisera databasen på nytt mellan varje test, för att bibehålla detta oberoende. Detta är en tidskrävan- de process. Således, föreslår man ett ramverk som på ett strukturerat sätt, låter tester bero på varandra, vilket de bevisar snabbar upp både testerna och reducerar antal kodrader för tester. Även Haller [44] argumenterar för att inte initialisera om databastillståndet efter varje testfall, och tillägger att tester därför ska exekveras i en systematisk ordning.

B.5

Diskussion

B.5.1

Resultat

Det finns uppenbarligen mycket forskning kring testning av databasapplikationer, men det är svårt att hitta verktyg som går att använda i dagsläget. I framtiden kommer förhoppnings- vis de verktyg som föreslås att realiseras och förhoppningsvis, förbättra sättet som databas- applikationer testas.

Det är förvånande hur få av de undersökta vetenskapliga artiklar, som förespråkar att skriva tester direkt i databasspråket, istället för det generella språket. Samtidigt pratas det flitigt om hur viktigt det är att mappningen av data mellan språken är korrekt. Av denna anledning förväntade jag mig att mer fokus skulle ligga på testning av mappningen av data och att det skulle vara ett eget område, snarare än att det skulle tas för givet.

B.5.2

Metod

Det var en utmaning att hitta vetenskapliga källor som låg på en tillräckligt praktisk nivå för detta arbete. Många källor presenterade prototyper på ramverk som var svåra att applicera i verkligheten och var ofta mycket abstrakta och matematiskt begrundade. Med andra ord, inget som en läsare med behov av att testa sin applikation i nuläget, har speciellt mycket nytta av. Däremot, hade dessa källor djupa teoriavsnitt, som bidrog till att besvara frågeställning- arna, och förstärka de metoder som föreslås i detta arbete med en teoretisk bakgrund. Mycket av det material som var anpassat för detta arbete, hämtades i stället från bloggar. Dessa hade också i syfte att ge läsaren förslag på hur man kan testa sin databas på direkten.

B.6. Slutsatser

B.6

Slutsatser

B.6.1

Varför bör man testa sin databas?

Behovet av att testa så funktioner fungerar som de ska, är inte unikt kopplat till databas- applikationer. Man kan dock lätt glömma bort att testa databasen, eftersom den oftast ligger under en applikation, vilket är det användaren interagerar med. Många förlitar sig på att databashanteraren gör det den ska, givet att den deklarativa naturen av databasspråk, döljer mycket från användaren. Fokus ligger därav ofta på korrektheten av ett uttryck (query) och att rätt information returneras, snarare än på hur den gjorde det.

Trots att mycket av ansvaret kan läggas på databashanteraren, måste man fortfarande sä- kerställa att man byggt databasen korrekt och enligt specifikationer. Databashanteraren ser egentligen bara till att upprätthålla de regler som utvecklaren definierat. Procedurer och funktioner bör fortfarande testas, för att verifiera korrektheten av sin applikation.

B.6.2

Vilka funktioner i databasen bör testas?

Statisk testning av databasstrukturen utgör en rimlig utgångspunkt. Har databasen de tabell- er som specificerats enligt krav och fyller varje tabell en klar funktion. Här kanske man inser att någon tabell är överflödig, och kan tas bort, eller att en tabell behöver läggas till för att bättre återspegla den värld som modellerats. Har tabeller rätt kolumner med rätt datatyper, även här är det viktigt att varje kolumn har ett syfte. Är relationerna mellan tabeller korrekta, refererar foreign keys till rätt primary keys. Är dessa inte korrekt definierade av utvecklaren, riskerar man att uppsatta regler inte upprätthålls av databashanteraren.

Efter man säkerställt att strukturen är korrekt, kan man angripa testningen av användardefi- nierade procedurer och funktioner. Är parametrar korrekta och har rätt datatyper. Returneras rätt datatyp från funktioner och utför procedurer önskade operationer. Aktiveras triggers vid rätt tillfälle, och med rätt utfall. Slutligen, beter sig procedurer, funktioner och triggers kor- rekt när de anropas från applikationen. Här kanske man upptäcker att mappningen mellan datatyper är inkorrekt och behöver omdefinieras.

B.6.3

Vilka utmaningar finns det kopplad till testning av en databas?

Databasapplikationer introducerar en ny dimension av utmaningar när det kommer till test- ning. Man kan inte, som med många andra applikationstyper, förlita sig på testers vanligtvis deterministiska natur, eftersom databastillståndet är avgörande för resultatet.

De flesta databasapplikationer är skrivna i flera språk, ett deklarativt databasspråk och ett imperativt generellt språk. Detta ställer krav på att all data som skickas mellan språken är mappade korrekt, samt att funktioner skrivet i ena språket, anropas korrekt i det andra.

B.6.4

Hur kan databasen testas med hänsyn till dessa utmaningar?

Framställning av testfall

Det första steget är att identifiera relevanta testfall. Har man ett projekt av mindre skala, kan det räcka med att testaren har tillräckligt med kunskap om databasens struktur och integrity constraints för att definiera intressanta testfall. Har man ett projekt av större skala, finns det framtagna lösningar från tidigare forskning, som ska automatisera processen av att generera testfall. Tyvärr, har ingen implementation av dessa, som är öppen för allmänheten hittats. Således, kan det fortfarande vara en utmaning för större projekt att definiera testfall.

B.6. Slutsatser

Efter testfall har framtagits, är det viktigt att placera databasen i ett känt tillstånd med känd data, detta kan göras på två sätt. Antingen används riktig data som ackumulerats från den verkliga databasen under körning, eller så används påhittad data, som genererats. Används riktig data riskerar man att inte få tillräckligt med variation på datan, men använder man påhittad data, står man istället inför problemet att generera denna data. Det finns verktyg som genererar data enligt avancerade algoritmer, men likt de verktyg som genererar testfall, hittades inga som i dagsläget går att använda. Det som utmärker ett sådant verktyg från ett som genererar massa slumpmässig data och som det finns verktyg för, är att de tar hänsyn till alla användardefinierade regler (integrity constraits), och utifrån dessa genererar intressant och giltig data, vilket är den stora utmaningen.

Exekvering av tester

Exekvering av de testfall som tagits fram görs antingen i ett generellt språk, genom ett testramverk, eller direkt i ett databasspråk. Det finns betydligt fler verktyg för testning i ge- nerella språk som Java, än det finns för databasspråk, exempelvis SQL. Av denna anledning kan det vara frestande att utföra testning av databasprocedurer i ett generellt språk (genom exempelvis JDBC [54]), som har sofistikerade testramverk. Anledningen till att man kanske vill avstå från denna frestelse, är att man nu måste kontrollera att data som skickas mellan språken är korrekt. Att ett problem ligger i datamappningen, snarare än i logiken, kan vara svårt att identifiera. Med det sagt, är det förstås viktigt att också testa interaktionen mellan språken, men i ett stadie där man säkerställt att databasprocedurerna fungerar korrekt. Ett sätt som kan effektivisera testning, är att låta tester återanvända data. Då man alltid måste placera databasen i känt tillstånd, är en vanlig metod att inför varje test, rensa databasen för att sedan initialisera den på nytt. Detta är tidskrävande och ger upphov till repetition av kod. Ett ramverk som föreslås av Christensen et al. [55], tillåter tester att på ett strukturerat sätt, bero av varandra. Detta ramverk är speciellt framtaget för enhetstestning.

Resultatverifiering

Som tidigare diskuterats, spelar databastillståndet en viktig roll för testningen av databas- applikationer. Detta är speciellt viktigt att tänka på under verifiering av testers utfall. För att avgöra om en funktion uppför sig korrekt, krävs att funktionen returnerar rätt resultat med avseende på databasens tillstånd. En funktion som testar att lagra data i en tabell, kan retur- nera att lagringen lyckats, men värdet som hamnade i tabellen kan fortfarande vara fel. Då databasen innan exekvering, placerats i ett känt tillstånd, bör detta inte vara svårt att verifie- ra. Man kan använda sig av loggar, som aktivt registrerar varje ändring i databasens tillstånd, eller direkt fråga databasen om det innehåll man är intresserad av, exempelvis genom ett ut- tryck query.

C

Jämförelse av

byggautomatiseringsverktyg -

Regina Hansson

C.1

Introduktion

Att automatisera olika delar i arbetsprocessen kan underlätta livet för utvecklare avse- värt. I projektet har byggautomatiseringsverktyget Maven använts för att bygga den Java- applikation som utgör projektets frontend. Alternativet som övervägdes var att använda Gradle till denna uppgift, där beslutet var mer slumpmässigt än informerat. Denna under- sökning är en informerad utvärdering av det beslutet.