Test-Driven Development (TDD) är välkänt för de flesta utvecklare. Acceptance Test-Driven Development (ATDD) fokuserar mer på verksamhetskraven i processen och är kanske inte lika välkänt. Båda teknikerna möjliggör kortare utvecklingscykler. Den här praktiska genomgången visar varför och hur.
Tatu Kairi
Principal Consultant
Tatu enjoys piña coladas, getting caught in the rain, is not into yoga and has half a brain.
Som någon som har arbetat med DevOps ett tag är det de transformationsresor jag har bevittnat som gör jobbet meningsfullt för mig.
Jag har sett hur mer samarbetsinriktade arbetssätt och tvärdisciplinära metoder går hand i hand: de låter utvecklare bredda sin kompetens. I slutändan skapar det bättre förståelse mellan specialiserade discipliner, så att slutmålet – en nöjd kund – kan nås bättre och snabbare.
Test-Driven Development (TDD) är en grundläggande teknik som de flesta utvecklare använder, medan Acceptance Test-Driven Development (ATDD) ligger närmare affärskraven i processen och därför kanske inte är lika välkänt bland utvecklare. Båda teknikerna möjliggör dock kortare utvecklingscykler och sätter kundens behov i centrum för projektarbetet.
Även om både TDD och ATDD används brett i branschen, utnyttjas de inte till sin fulla potential. Här visar jag hur du kan frigöra de möjligheter som saknas.
Tillbaka till grunderna: skifta vänster
All mjukvara går igenom följande faser under sin livstid:
Först får någon en idé som löser ett problem eller gör det möjligt att göra något som tidigare varit utom räckhåll. Det leder till vissa krav, som sedan planeras – både tekniskt och ekonomiskt – för att kunna genomföras. Därefter genomförs implementationen. Sedan behöver lösningens kvalitet bedömas. Vi behöver verifiera att mjukvaran fungerar tekniskt som avsett och validera att den uppfyller sin specifikation. Slutligen behöver mjukvaran underhållas tills den tas ur bruk.
Glöm inte: dessa faser är oföränderliga. Mjukvaruutveckling kan med andra ord inte hoppa över någon av faserna – var och en måste hanteras vid någon tidpunkt. Avsaknad av krav eller uteblivet underhåll betyder bara att du har hanterat fasen mycket bristfälligt – men du har ändå hanterat den.
Syftet med Agile och DevOps är inte att undvika arbete, utan att parallellisera det genom smarta arbetssätt och automatisering – det kallas att skifta vänster.
När det första kravet formuleras går vi direkt vidare till att planera, implementera, testa och släppa det till slutanvändarna, samtidigt som andra krav skapas, planeras, implementeras, testas och släpps parallellt. Vi vill påbörja varje fas för en funktion så tidigt som möjligt. Med andra ord strävar Agile och DevOps efter att skifta så mycket arbete som möjligt åt vänster.
Test-Driven Development (TDD)
Ett sätt att ”skifta vänster” är att arbeta med Test-Driven Development (TDD). Metoden ”upptäcktes” ursprungligen i början av 2000-talet och har sedan dess blivit en självklar del av en bra utvecklares verktygslåda. Den största fördelen är att den flyttar en del av testarbetet – den tekniska enhetstestningen – så att den sker parallellt med själva implementationen. Det är bra, eftersom koden och testerna som verifierar den färdigställs hand i hand, vilket ställer högre krav på utvecklarna.
Att skifta vänster gjorde det inte bara möjligt att parallellisera arbetet, utan skapade också ett helt nytt sätt att använda testning som ett designverktyg för koden som implementeras. Det ger bättre kodkvalitet från början, utöver att arbetet flyttas åt vänster.
Låt oss ta ett litet exempel i Python på hur vi gjorde förr, innan TDD.
Vi behöver en Thingamabob som tar emot autentiserade anslutningar över nätverket för att göra saker med den. Utifrån denna enkla specifikation kanske vi skapar något i stil med ovanstående.
Och naturligtvis skapar vi även det tillhörande enhetstestet.
Bra, eller hur? Med TDD kan vi alltså säkerställa att vi aldrig ”glömmer” att skapa testfallet också. Men låt oss se vad som händer när vi börjar med att bara skriva testfallet.
Jag behöver en Thingamabob för att göra saker.
Så där! Vad kan jag implementera härnäst för att få testet att gå igenom ...
Det verkar som att jag behöver strukturera min kod så att anslutningen hanteras smidigt i bakgrunden. Jag vet, jag använder Python’s context managers för att åstadkomma det!
I det exemplet skapade vi ett mycket bättre gränssnitt för Thingamabob, där slutanvändaren – den anropande koden – inte behöver bekymra sig om att hantera anslutningen. Den senare implementationen kräver inte bara färre rader kod, utan är också mer framtidssäker. Om anslutningen ändras på något sätt går testfallet inte sönder, eftersom det bara ska verifiera att vi ”gör saker”. Det första exemplet kan verka enklare, men det är det inte. Testfallet vägledde våra designbeslut mot bättre kod.
Acceptance Test-Driven Development (ATDD)
TDD är en princip som har förbättrat implementeringen av kod genom att inte bara kombinera teknisk testning med implementation – och därmed möjliggöra parallellisering – utan också genom att öppna upp för ett helt nytt och oväntat arbetssätt.
Acceptanstestning har många namn, bland annat User Acceptance Testing (UAT), end-to-end-testning, Alpha-testning och Beta-testning. I dag har nya verktyg för testautomatisering gjort det möjligt att automatisera detta testområde, som tidigare kunde påbörjas först när större delen av, om inte allt, implementationsarbete var klart. Med open source-verktyg som Robot Framework eller Cucumber kan vi automatisera slutanvändarens interaktion med vår applikation i stället för att göra den manuellt.
Man kan undra varför en metod som fokuserar så mycket på att automatisera manuell testning presenteras tillsammans med den jämförelsevis tekniska metoden TDD. Jag kan försäkra dig om att det inte bara beror på att de låter likadant. ATDD gör det också möjligt för oss att ”skifta vänster” arbete som tidigare utfördes längre fram i processen.
Genom att automatisera det här sista teststeget slipper människor manuellt arbete, vilket är en av DevOps viktigaste grundprinciper. Precis som med TDD kan vi flytta arbetet ännu längre åt vänster genom att använda Acceptance Test-Driven Development (ATDD), en metod där vi börjar skriva testfall mycket tidigare än tidigare: redan när vi samlar in krav.
I grunden bygger ATDD på en annan välbeprövad metod: user stories, som används för att definiera våra specifikationer med en informell beskrivning på naturligt språk ur den tänkta slutanvändarens perspektiv.
Förr i tiden kunde mjukvaruutveckling se ut ungefär så här:
Skriv specifikationen för ett krav i ett dokument
Lägg tid på att förstå dokumentet och planera, efter många diskussioner, implementationen utifrån en vag uppfattning om vad som efterfrågas
...implementera funktionen som kod...
Lägg ännu mer tid på att förstå om implementationen fungerar som avsett och om den uppfyller det ursprungliga kravet …
Gå (oftast) tillbaka och implementera funktionen på ett annat sätt när du har fått mer information
Ny information dyker upp: upprepa steg 3–5, om och om igen.
Ett arbetsflöde för Acceptance Test-Driven Development (ATDD) ser i stället ut så här:
Skriv specifikationen i ett enhetligt format som testfall tills alla förstår funktionen.
Implementera funktionen samtidigt som du automatiserar testfallet.
Om ny information som motiverar en ändring framkommer upprepar du steg 1 och fortsätter.
Verifiera resultatet genom att köra testfallet. Klart.
Exempel gjort med Robot Framework
Vi får inte bara fördelarna med user story-formatet, som hjälper oss att förstå problemet bättre, utan fokuserar också diskussionen om funktionen ur slutanvändarens perspektiv. Det tvingar i sin tur alla deltagare – verksamhet, design, utvecklare, testare och drift – att se helheten och förstå varför de gör arbetet från första början.
När alla förstår vad som står på spel blir testfallet en spårbar enhet genom livscykelns alla andra faser. Det innebär att det versionshanteras tillsammans med koden i versionshanteringssystemet, fungerar som levande dokumentation av verksamhetskravet och alltid kan köras för att bevisa att funktionen fungerar.
TDD + ATDD
Jag har visat hur teknisk enhetstestning med TDD har gett testfall rollen som ett verktyg för koddesign. På samma sätt gör ATDD det inte bara möjligt att automatisera den till stor del manuella testfasen, utan lyfter också in den i kärnan av kravspecifikationen.
Utformar du enklare kod med TDD? Har ATDD gjort det enklare för dig att samarbeta med verksamheten och utvecklingsteamet? Berätta gärna vad du tycker eller kom med förslag på framtida ämnen som jag kan skriva om på vår kontaktsida.
Upptäck utbildningsutbudet.
- DevOps
- CI/CD
Subscribe to our newsletter
Related blogs