Det finns flera skäl till att skriva automatiserade tester, och det kan verka relativt enkelt. Att skriva ”bra” automatiserade tester är dock betydligt svårare och kräver omfattande erfarenhet och medveten träning.
I det här inlägget har jag sammanställt några (övergripande) kriterier som måste uppfyllas för att de automatiserade testerna ska bli bra. Kriterierna definieras i tolv egenskaper, och när dessa är uppfyllda uppnås definitionen av ”bra” automatiserade tester.
Här är några övergripande mål som kan vara tillämpliga:
- Testerna ska hjälpa oss att förbättra kvaliteten.
- Testerna ska hjälpa oss att förstå systemet.
- Tester ska minska (inte öka) risken.
- Tester ska vara lätta att köra.
- Tester ska vara lätta att skriva och underhålla.
- Tester ska kräva minimalt underhåll när systemet utvecklas runt dem.
Tester ska hjälpa oss att förbättra kvaliteten
1. Test som specifikation
Om du använder TDD – testdriven utveckling eller BDD – beteendedriven utveckling (test-först-utveckling), ger testerna dig ett sätt att fånga upp vad systemet kommer att göra innan du börjar bygga det. Att tänka igenom olika scenarier för att omvandla dem till tester hjälper oss att identifiera de områden där kraven är tvetydiga eller motstridiga. En sådan analys förtydligar syftet med specifikationen, vilket leder till en mer exakt design och förbättrar programvarans kvalitet.
2. Felförebyggande
Automatiserade tester upptäcker buggar, men det är inte huvudsyftet med testautomatisering. Automatiserad testning förhindrar att buggar införs. Tänk på automatiserade tester som ett sätt att avvisa fel, vilket förhindrar att buggar återkommer i vår programvara efter att vi har säkerställt att den är felfri. När vi har bra och fullständiga regressionstester kommer det inte att finnas några buggar, eftersom testerna kommer att påpeka felen redan innan vi ens checkar in vår kod.
3. Identifiering av fel
Om de automatiserade testerna är relativt små (det vill säga att vi endast testar ett enda beteende i varje test) kommer vi att kunna lokalisera felet snabbt, utifrån vilket test som misslyckas. Men för att uppnå detta måste vi skriva tester för alla möjliga scenarier för att täcka varje enhet i programvaran. Testerna får aldrig innehålla tvetydigheter. Därför är det avgörande att vi håller testerna så små och enkla som möjligt (låg komplexitet, enhetligt format och att varje test endast testar ett enda beteende).
Testerna ska hjälpa oss att förstå systemet
4. Test som dokumentation
Automatiserade tester kan tydligt belysa hur koden ska fungera. De visar vad resultatet ska bli (det anger det förväntade resultatet av ett eller flera uttryck).
Om vi vill veta hur systemet utför en viss åtgärd kan vi starta felsökaren, köra testet och gå igenom koden steg för steg för att se hur den fungerar. Enhetstesterna fungerar som en form av dokumentation för systemet.
Tester bör minska (inte öka) risken
5. Test som säkerhetsnät
Att ändra äldre kod är riskabelt eftersom vi ofta inte vet vad vi kan förstöra, och det är också svårt att veta om vi har förstört något! Vi måste arbeta mycket långsamt och försiktigt och göra en hel del manuell analys innan vi gör några ändringar.
Men när vi arbetar med kod som har en automatiserad testserie kan vi arbeta mycket snabbare. Testerna upptäcker oväntade bieffekter av ändringarna och meddelar oss om vi har förstört något. På det här sättet fungerar de automatiska testerna som ett säkerhetsnät som gör att vi vågar ta risker.
6. Ingen testrisk
Vi måste vara försiktiga så att vi inte inför nya typer av problem i systemet till följd av automatiserad testning. Håll testkoden åtskild från produktionskoden för att undvika att skapa testspecifika beroenden i systemet (särskilt viktigt för enhetstestkod). All testspecifik kod och alla testspecifika bibliotek måste länkas in av testet och endast i testbyggnaden och i testmiljön. Testberoenden och testkod får aldrig finnas i den slutliga koden när den byggs för produktion.
Testerna bör vara lätta att köra
Det finns fyra specifika egenskaper som gör automatiserade tester lätta att köra. Med dessa fyra egenskaper kan du helt enkelt klicka på en knapp (eller ännu bättre: låta dem startas automatiskt) för att få den värdefulla feedback som testerna ger:
-
Testerna måste vara helt automatiserade så att de kan köras utan ansträngning.
- Testerna måste vara självutvärderande så att de kan upptäcka och rapportera fel utan manuell granskning.
- Testerna måste vara repeterbara så att de kan köras flera gånger med samma resultat.
- Varje test bör vara självständigt så att det kan köras på egen hand.
7. Helt automatiserade tester
Ett test som kan köras utan någon manuell inblandning är ett helt automatiserat test. Att uppfylla detta kriterium är en förutsättning för att uppfylla de övriga.
8. Självutvärdering
Ett självutvärderande test kan innehålla allt som testet behöver för att verifiera att det förväntade resultatet är korrekt. Testet meddelar oss endast när resultatet inte har godkänts; följaktligen kräver en felfri testkörning ingen manuell insats alls.
9. Repeterbara tester
Ett repeterbart test kan köras om och om igen och ger fortfarande exakt samma resultat utan någon mänsklig inblandning eller analys mellan körningarna.
Testerna bör vara lätta att skriva och underhålla
När vi ändrar beteendet i en del av ett system bör vi förvänta oss att endast ett fåtal tester påverkas av våra ändringar. En av fördelarna med testautomatisering är att det blir enkelt att göra ändringar. Vi bör därför alltid sträva efter att se till att våra tester inte gör det motsatta (gör ändringar svårare). Testerna bör kräva minimalt underhåll i takt med att systemet utvecklas runt dem.
10. Enkla tester
Lägg fokus på testerna snarare än på hur man faktiskt kodar dem. Det innebär att testerna måste vara enkla/triviala (lätta att läsa, lätta att skriva och lätta att underhålla). Vi bör sträva efter att verifiera ett villkor per test genom att skapa en separat testmetod för varje unik kombination av villkor. Varje testmetod bör testa systemet genom en enda väg i systemet.
11. Uttrycksfulla tester
Ett bibliotek med hjälpmetoder som bygger upp ett domänspecifikt testspråk gör det möjligt för den som skriver testkoden att uttrycka de begrepp som hen vill testa, utan att behöva översätta sina tankar till mycket mer detaljerad kod.
12. Dela upp problemen
Håll testkoden åtskild från produktionskoden (behåll strukturen och logiken från produktionskoden, men i en parallell struktur). Varje test bör fokusera på ett enda problem för att undvika komplicerade och otydliga tester.
Sammanfattning
Det finns en skillnad mellan ett test och ett bra test, men det är ofta svårt att veta hur man definierar ett test som är ”bra”. I denna checklista har jag delat med mig av 12 kännetecken för god testautomatiseringspraxis, vilket i sin tur resulterar i tester som är lätta att skriva och som är lätta att underhålla – båda dessa faktorer är mycket viktiga för ett system.