Vad är automatiserad testning?
I den här lektionen får du lära dig om fördelarna med automatiserad testning och vilka typer av tester du kan utföra. Du får också lära dig vad som gör ett bra test och introduceras för några av de testverktyg som är tillgängliga för dig.
Vad är automatiserad testning?
Automatiserad testning använder programvara för att köra koden och jämföra de faktiska resultaten med de resultat du förväntar dig. Jämför detta med undersökande eller manuell testning, där en människa vanligtvis följer instruktionerna i en testplan för att verifiera att programvaran fungerar som förväntat.
Manuell testning har sina fördelar. Men när din kodbas växer i storlek kan testningen av alla funktioner manuellt (inklusive gränsfall) bli repetitiv, omständlig och felbenägen. Automatiserad testning kan hjälpa till att eliminera en del av den här bördan och göra det möjligt för manuella testare att fokusera på vad de gör bäst: att se till att dina användare får en positiv upplevelse med din programvara.
Testpyramid
När vi tänker på automatiserad testning är det vanligt att separera tester i lager. Mike Cohn föreslår detta koncept, känt som testpyramid, i sin bok Succeeding with Agile.
Även om detta är en förenklad version av Cohns modell visar konceptet att du fokuserar det mesta av din ansträngning på att skriva tester som verifierar grundnivåerna i din programvara (pratbubblan 1 i pyramiden), till exempel funktioner, klasser och metoder. Du fokuserar gradvis mindre eftersom funktioner kombineras, till exempel på användargränssnittsskiktet (pratbubblan 2 i pyramiden). Tanken är att om du kan kontrollera att varje komponent på lägre nivå fungerar som förväntat i isolering behöver tester på högre nivåer bara verifiera att flera komponenter fungerar tillsammans för att få det förväntade resultatet.
När ska jag skriva tester?
Svaret beror främst på dina behov och erfarenhet av att skriva tester.
Det är aldrig för sent att börja lägga till tester för kod som du redan har skrivit och distribuerat. Detta gäller särskilt för funktioner som ofta bryter eller kräver mest arbete från testteamet.
När du relaterar testning till pipelines för kontinuerlig integrering och kontinuerlig leverans hör du om kontinuerlig testning och växling till vänster.
Kontinuerlig testning innebär att tester körs tidigt i utvecklingsprocessen när varje ändring flyttas genom pipelinen. Att flytta till vänster innebär att överväga programvarukvalitet och testning tidigare i utvecklingsprocessen.
Utvecklare lägger till exempel ofta till testfall när de utvecklar sin funktion och kör hela testpaketet innan de skickar ändringen till pipelinen. Den här metoden hjälper till att se till att den funktion som de skapar fungerar som förväntat och att den inte bryter befintliga funktioner.
Här är en kort video där Abel Wang, molnrådgivare på Microsoft, förklarar hur du säkerställer att du bibehåller kvaliteten i din DevOps-plan.
Fråga Abel
Att flytta vänster kräver ofta att testare engagerar sig i designprocessen, även innan någon kod för funktionen skrivs. Jämför detta med "överlämningsmodellen", där testteamet får nya funktioner att testa först när programvaran har utformats och skrivits. En bugg som upptäcks sent i processen kan påverka teamets leveransschema och buggar kan identifieras veckor eller till och med månader efter att utvecklaren ursprungligen skapade funktionen.
Kompromissen
Med automatiserad testning finns det en kompromiss. Även om automatiserad testning gör det möjligt för testare att fokusera sin tid på att verifiera slutanvändarupplevelsen, kan utvecklare behöva ägna mer tid åt att skriva och underhålla sin testkod.
Poängen med automatiserad testning är dock att se till att testarna endast får kod av högsta kvalitet, kod som har visat sig fungera som förväntat. Därför kan utvecklare frigöra en del av sin tid genom att behöva hantera färre buggar eller undvika kodomskrivningar på grund av ett gränsfall som de inte ursprungligen hade övervägt.
Fördelar har lagts till
Dokumentation och möjligheten att omstrukturera koden enklare är två ytterligare fördelar med automatiserad testning.
Dokumentation
Manuella testplaner kan fungera som en typ av dokumentation om hur programvara ska bete sig och varför vissa funktioner finns.
Automatiserade tester kan ha samma syfte. Automatiserad testkod använder ofta ett läsbart format för människor. Den uppsättning indata som du anger representerar värden som användarna kan ange. Varje associerad utdata anger det resultat som användarna bör förvänta sig.
Faktum är att många utvecklare följer metoden för testdriven utveckling (TDD) genom att skriva sin testkod innan de implementerar en ny funktion. Tanken är att skriva en uppsättning tester, ofta kallade specifikationer, som till en början misslyckas. Sedan skriver utvecklaren inkrementellt kod för att implementera funktionen tills alla tester har godkänts. Specifikationerna dokumenterar inte bara kraven, utan TDD-processen hjälper till att säkerställa att endast den nödvändiga mängden kod skrivs för att implementera funktionen.
Refaktorisering
Anta att du har en stor kodbas som du vill omstrukturera för att vissa delar ska köras snabbare. Hur vet du att dina refaktoriseringsåtgärder inte leder till att delar av programmet går sönder?
Automatiserade tester fungerar som en typ av kontrakt. Det innebär att du anger indata och förväntade resultat. När du har en uppsättning klara tester är det bättre att experimentera och omstrukturera koden. När du gör en ändring behöver du bara köra dina tester och kontrollera att de fortsätter att passera. När du har uppfyllt dina refaktoriseringsmål kan du skicka in ändringen till bygg-pipelinen så att alla kan dra nytta av det, men med en lägre risk för att något går sönder.
Vilka typer av automatiserad testning finns det?
Det finns många typer av automatiserad testning. Varje test har ett separat syfte. Du kan till exempel köra säkerhetstester för att kontrollera att endast behöriga användare kan komma åt en programvara eller någon av dess funktioner.
När vi nämner kontinuerlig integrering och bygg-pipelinen refererar vi vanligtvis till utvecklingstestning. Utvecklingstestning avser tester som du kan köra innan du distribuerar programmet till en test- eller produktionsmiljö.
Till exempel kontrollerar lint-testning, en form av analys med statisk kod, källkoden för att avgöra om den överensstämmer med teamets stilguide. Kod som formateras konsekvent är enklare för alla att läsa och underhålla.
I den här modulen arbetar du med enhetstestning och kodtäckningstestning.
Enhetstestning verifierar de mest grundläggande komponenterna i ditt program eller bibliotek, till exempel en enskild funktion eller metod. Du anger en eller flera indata tillsammans med det förväntade resultatet. Testlöparen utför varje test och kontrollerar om de faktiska och förväntade resultaten matchar.
Anta till exempel att du har en funktion som utför en aritmetikåtgärd som innehåller division. Du kan ange några värden som du förväntar dig att användarna ska ange tillsammans med kantfallsvärden som 0 och -1. Om en viss indata genererar ett fel eller undantag kan du kontrollera att funktionen genererar samma fel.
Kodtäckningstestning beräknar procentandelen av din kod som omfattas av enhetstesterna. Kodtäckningstestning kan innehålla villkorsstyrda grenar i koden för att säkerställa att en funktion omfattas.
Ju större din kodtäckningsprocent är, desto mer säker kan du vara på att du inte senare upptäcker en bugg i kod som inte har testats fullständigt. Du behöver inte nå 100 procents kodtäckning. När du börjar kommer du förmodligen att märka att du har en låg procentandel, men det ger dig en startpunkt där du kan lägga till ytterligare tester som omfattar problematisk eller ofta använd kod.
Hålla enhetstester isolerade
När du lär dig om enhetstestning kan du höra termer som mocks, stubs och beroendeinmatning.
Kom ihåg att ett enhetstest bör verifiera en enskild funktion eller metod och inte hur flera komponenter interagerar. Men om du har en funktion som anropar en databas eller webbserver, hur hanterar du det?
Ett anrop till en extern tjänst bryter inte bara isoleringen, utan det kan göra saker och ting långsammare. Om databasen eller webbservern slutar fungera eller om den inte är tillgänglig på annat sätt kan anropet också störa testkörningen.
Med hjälp av tekniker som mocking och beroendeinmatning kan du skapa komponenter som efterliknar den här externa funktionen. Du får ett exempel senare i den här modulen.
Senare kan du köra integreringstester för att kontrollera att programmet fungerar korrekt med en riktig databas eller webbserver.
Vad gör ett bra test?
Du kommer att bättre kunna identifiera ett bra test eftersom du får erfarenhet av att skriva egna tester och läsa tester skrivna av andra. Här följer några riktlinjer för att komma igång:
- Testa inte för testningens skull: Dina tester bör tjäna ett syfte utöver att vara ett checklistobjekt att korsa. Skriv tester som verifierar att din kritiska kod fungerar som den är avsedd och inte bryter befintliga funktioner.
- Håll testerna korta: Testerna bör slutföras så snabbt som möjligt, särskilt de som sker under utvecklings- och byggfaserna. När testerna körs när varje ändring flyttas genom pipelinen vill du inte att de ska vara flaskhalsen.
- Kontrollera att testerna är repeterbara: Testkörningar bör ge samma resultat varje gång, oavsett om du kör dem på datorn, en medarbetares dator eller i bygg-pipelinen.
- Håll testerna fokuserade: En vanlig missuppfattning är att tester är avsedda att täcka kod som skrivits av andra. Vanligtvis bör dina tester endast omfatta din kod. Om du till exempel använder ett grafikbibliotek med öppen källkod i projektet behöver du inte testa biblioteket.
- Välj rätt kornighet: Om du till exempel utför enhetstestning bör ett enskilt test inte kombinera eller testa flera funktioner eller metoder. Testa varje funktion separat och senare skrivintegreringstester som verifierar att flera komponenter interagerar korrekt.
Vilka typer av testverktyg är tillgängliga?
Vilka testverktyg du använder beror på vilken typ av program du skapar och vilken typ av testning du vill utföra. Du kan till exempel använda Selenium för att utföra användargränssnittstestning på många typer av webbläsare och operativsystem.
Oavsett vilket språk ditt program är skrivet i är många testverktyg tillgängliga för dig att använda.
För Java-program kan du till exempel välja Checkstyle för att utföra linttestning och JUnit för att utföra enhetstestning.
I den här modulen använder vi NUnit för enhetstestning eftersom det är populärt i .NET-communityn.