Klassificering av testdata

Typewriter-2

Testdata är ett kärt ämne så jag tänkte vi kunde prata lite om olika typer av testdata och hur man kan klassificera och hantera dessa. Jag tänkte begränsa mig till persistent data.

Ett grundkriterie för robusta tester är att man har kontroll över systemets tillstånd. Ett och samma test kan ge olika resultat om systemets tillstånd skiljer sig åt mellan testkörningar. Än värre är om testerna har ett inbördes beroende. T.ex. om man byter exekveringsordning på två tester så får man ett annat resultat. Det kan t.ex. bero på att testerna delar data och det ena testet förändrar datan. Det är dock inte praktiskt möjligt att helt kontrollera systemets tillstånd – iallafall inte för systemtester – men man bör eftersträva att ha så stor kontroll som möjligt.

Vad är det som påverkar systemets tillstånd? All data som inte återställs eller rensas förändrar tillståndet hos systemet. Denna data kan komma i en uppsjö av olika varianter, ex ; cache, fil, kö, databas, klassvariabler etc. För att vara helt säker på att systemet är återställt måste man starta om det, samt rensa alla persistenta källor mellan varje test. Det kan man sällan göra av praktiska skäl – då skulle testerna ta för lång tid att exekvera. Dock brukar det finnas möjlighet att kontrollera den persistenta datan (icke-dynamiska data) – som jag här tänkte representera med en databas.

Den persistena datan kan klassificeras i tre huvudkategorier; ”färsk”, ”oföränderlig” och ”delad”.

”Färsk”, är data som endast existerar under livstiden av ett oberoende test. Det kan vara en förutsättning för testet eller data som skapas av testet. Efter testet så återställs systemet genom att rensa bort den nya datan. Ex:

Tänk er ett system med möjlighet att registrera unika kunder – inte helt ovanligt. Vi testar att registrera ”Nils” vilket genererar nya rader i diverse tabeller i databasen. För att kunna köra exakt samma test igen måste datan knuten till kunden ”Nils” tas bort – då systemet endast tillåter unika kunder. Det gör man förslagsvis i någon post-metod (tearDown) med hjälp av lämplig systemmetod (deleteCustomer). Om dylik systemmetod saknas (låg testabilitet) blir det knepigare. Ska man skriva specifik testkod för att ta bort denna data? Inte helt självklart. Då kan det vara bättre att undersöka möjligheterna till att göra en ”transaction rollback”.

”Oföränderlig”, är data som inte förändras under sin existens. Existensen definieras som livstiden av alla tester. Det kanske vanligaste exemplet på denna typ av data är konfigurering Då denna data inte förändras för någon av testerna blir den lätthanterlig. Förslagsvis laddar man denna data innan första testet körs. Det finns ingen anledning att rensa eller återställa denna data mellan testerna.

Slutligen kommer vi till den mest komplexa datatypen – ”delad”. Precis som ovan typ existerar denna data under livstiden av alla tester. Skillnaden ligger i att datan kan förändras. Ex:

Tänk er att vi förladdar databasen med ett förutbestämt set av kunder. Vi hämtar sedan en kund från detta set inför varje specifikt test och använder som testdata. Problem uppstår när ett test modifierar någon egenskap hos en specifik kund och ett annat test återanvänder just den kunden. Säg att vi har ett test som markerar en kund som obsolet. Om ett annat test återanvänder den kunden kommer det testet att fallera då kunden inte är brukbar.

Man bör eftersträva att endast använda ”färsk” och ”oföränderlig” data. I praktiken kan det dock vara svårt pga låg testabilitet etc. Då kan man försöka att bryta upp sin ”delade” data i ovan två typer. Det ger mer kontroll och bättre robusthet. Om vi använder ovan exempel så skulle vi åstadkomma detta genom att göra kundens egenskaper till ”färska”. Huruvida det är praktiskt lämpligt beror på hur systemet är implementerat.

 

 

Skapa persistent testdata

Typewriter-2

En fråga som ploppar upp med jämna mellanrum är hur man bäst skapar testdata för sina automatiska tester. Om vi begränsar diskussionen till persistent data så finns det två huvudfalanger; populera datan med egna testscript eller genom att använda systemets gränssnitt.

Den första varianten betyder i praktiken (oftast) att skapa testspecifika anrop till databasen för att populera datan. Att generera testdatan m.h.a. systemets gränssnitt betyder att testet ropar på någon inneboende metod i systemet och låter systemet skapa datan. Denna metod kan antingen vara publik eller intern.

Så vad är för/nackdelar med dessa två varianter?

Att skapa egna script för testdatagenerering innebär att dessa måste underhållas när systemet förändras. Det kan höja förvaltningskostnaden för testerna. Vidare ökar komplexiteten då kan det finnas fel i själva testscripten.

Å andra sidan, om man använder interna systemmetoder för att skapa datan finns risk att man skapar datan felaktigt – det är inte syftet med den interna metoden. Publika systemmetoder bör representera verkligheten, men om vi har defekter i systemet kan vi inte generara testdatan och därmed inte heller utföra våra tester. Vi kan hamna i en situation där alla tester går sönder pga att en systemfunktionalitet inte fungerar.

Vad bör vi överväga när vi väljer strategi? Låt oss titta på ytterligheter för när respektive metod fungerar bäst.

Ponera ett befintligt system med små förändringar där testerna exekveras sällan (några ggr per release). Om vi här nyttjar en strategi med testscript så bör underhållet av testscripten vara minimalt. När testerna väl exekveras så vill man inte riskera att en stor del av testerna fallrar pga att man inte kan sätta upp förutsättningarna. Då får man ett meningslöst resultat.

Motsatsen är ett system med stora förändringar. Om testerna exekveras ofta (flera ggr per dag) fångar man snabbt upp eventuella problem med att systemet inte kan generera testdatan. Här ter sig nyttjande av gränssnitt som mer fördelaktigt. Det förutsätter naturligtvis att man snabbt rättar upp problemen.

Hypotesen blir därmed; om ditt system är under utveckling (eller på andra sätt utsatt för stora förändringar), exekvera dina automatiska tester ofta och nyttja systemets gränssnitt för att generera din testdata.

I slutändan gäller det dock att vara pragmatisk och inte låta religös övertygelse styra.

 

 

 

 

Tankar och tips kring förvaltningsbar webb

Typewriter-2

Var på ett föredrag för ett tag sen som var rätt intressant. Ämnet var om att bygga förvaltningsbar och säker webb.
Några viktiga saker som jag fick med mig är bland annat hur jobbigt det kan bli med underhållet av webb när man plockar in tredjeparts ramverk som behöver uppdateras och patchas. Betänk hur många siter som använder tekniker såsom JQuery, dojo, Spring MVC, Struts mm. En del av ramverken som används ute i webbläsaren kan man gå in och (ofta) läsa vilken version som används och vilka sårbarheter som kan tänkas finns som är patchat i en senare version av ramverket. Det är ganska enkelt att hitta vilka sårbarheter som har fått patchar i senare versioner av ramverken då dessa brukar publiseras när det finns rättningar. Måste motvilligt medge att jag kanske inte alltid tänkt hela varvet runt när det gäller att införa nya ramverk och versioner av ramverk vad det innebär i längden när det gäller att driva en site och underhålla koden.

Men den viktiga frågan du själv ska ställa dig!
Hur ser det ut med produkten/siten/mm som jag testar? vilka ramverk och versioner använder vi? har vi koll på patchnivåer? har våran drift/underhållsorganisation koll på vilka ramverk och versioner vi använder? Kan jag själv testa om vi infört de nödvändiga patcharna? Vet testarna i projektet/organisationen hur man testar möjliga problempunkter?

Hur gör man då för att kolla tex vilken version av JQuery som används? Det är ganska enkelt, om du använder IE så ta upp en valfri site och tryck F12, nu kan du läsa/söka i HTML’en och i många fall kan hitta tex vilken version av jquery som används. Kör du firefox så öppna webbutvecklar verktyg (eller firebug mm) och kolla källkoden. Med dessa enkla verktyg kan du även kolla css och script på sidan.

När man kommer till backend systemen så är det inte fullt lika enkelt att finna vilka versioner och ramverk som används så här är det enklaste att helt enkelt be någon utvecklare/driftstekniker gå igenom och kolla vad som används och tillsammans får man gå igenom potentiella svagheter.

För egen del så ingår numera denna bit som en naturlig del när jag börjar arbetet med en ny webbsite/app.
* Gå igenom vilka ramverk och versioner som används
* Kolla om några ramverk öppet visar vilken version som används
* Har vi någon policy för hur man får införa nya ramverk? Skapa en sådan om den saknas
* Utifrån vilka ramverk och versioner som används gå igenom om det kommit nyare version som täpper exempelvis säkerhetsluckor

Givetvis finns det mycket mer att tänka på men det här är en bra start :-)

 

 

Ta fram en testplan på 10 minuter!

Typewriter-2

2011-10-03 STARWest, Anaheim, CA, James Whittaker (Testchef på Google)

slänger upp en slide om att testplaner ska ta 10 minuter att ta fram!

Engagerat halvskriker han åt oss att sluta producera material som ingen ändå bryr sig om eller läser och en testplan som inte leder till testfall är slöseri med tid!

Utan att orda för mycket om processen för hur Google kom fram till sin metodik kan man i alla fallsäga att James provocerade sina testare att fokusera på det viktigaste, det som ger det faktiska resultatet, genom att tvinga fram det med en extrem tidsbrist, d.v.s. 10 minuter….

Så småningom utvecklade sig det hela till Googles nya standard för testplaner, ACC.

ACC står för Attributes, Components and Capabilities och hjälper till att identifiera ”testområden”  utifrån dessa tre synsätt ….

Attributes på ett system skulle kunna vara snabb, säker, användbar, stabil etc.

Components kan vara saker som en toolbar, en flik, en modul, etc. I stort de byggstenar som vårt system/applikation består av.

Capabilities är saker som att ladda webbsida, spara kundorder, verifiera användare m.m.

Ok, så det innebär att vi har en bas att ta fram testfall ifrån och därmed är testplanen klar!

Ingen text om bakgrund, miljöer, vilka verktyg som kommer användas etc. utan bara totalt fokus på vad som kommer testas! Enkelt i teorin och kanske en inspiration att försöka minska all administrationsoverhead vi ibland tenderar att (frivilligt?) lägga in i vårt testarbete!

 

 

Visualisera testerna (om testdesign, krav och modellbaserad test)

Typewriter-2

Jag har i några av mina tidigare uppdrag jobbat med att automatisera test och jobbat med modellbaserad test som testdesignteknik. Vad som slagit mig vid flera tillfällen är att jag med hjälp av att tillsammans med kravställare ta fram en modell av kravet (eller koncept) så har vi hittat potentiella fel eller onödigt komplexa scenarier (ökad utvecklingstid) redan innan utvecklarna hunnit börja koda. Sen förenklar den visuella designen möjligheterna att föra en diskussion kring testdesignen med både utvecklare, testare och kravställare. Som jag ser det ett bra komplement till/eller ersättning för scriptade manuella testfall.

Metoden att skapa modeller som testdesign kan även hjälpa till att på ett strukturerat sätt börja skapa testdesign tidigare i projektet. Ytterliggare en potentiell fördel är att även mindre erfarna testare får ett bra stöd i att skapa en väl överskådlig testdesign på ett strukturerat sätt. När man sen kommer till att underhålla testdesignen så är det ofta enklare att underhålla en modell än scriptade testfall. Med en approach att skapa modeller även för manuella test så vinner vi dessutom mycket när det kommer till att skapa en automatisering som i många fall kommer att kunna använda samma modeller.