Viktigheten av kode coverage i programvaretesting
Når man utvikler programvare, er det uunngåelig at feil oppstår i koden. Disse feilene kan manifestere seg som syntaksfeil, logiske feil, runtime-feil, ytelsesproblemer, datafeil eller enda mer alvorlige problemer.
Den nærmest konstante tilstedeværelsen av feil under programmering gjør testing av programvare til en kritisk fase i utviklingsprosessen. Grundig og effektiv testing sikrer ikke bare høykvalitets programvare som møter brukernes behov, men også programvare som overholder gjeldende forskrifter og har minimalt med sikkerhetssårbarheter som kan utnyttes av ondsinnede aktører.
Programvaretesting kan utføres gjennom forskjellige metoder, inkludert automatisert testing, enhetstesting, integrasjonstesting og fullstendig systemtesting.
Et sentralt spørsmål som ofte dukker opp under testing, er hvordan man kan være sikker på at programvaren er grundig testet. Er testene som er utført tilstrekkelige? Har man testet alle deler av programvaren, eller er det kodefragmenter som ikke er dekket av testene?
Disse spørsmålene er svært relevante i testprosessen, og det er her viktigheten av kode coverage kommer inn i bildet.
Kode coverage, eller kodedekning, er en metode for programvaretesting som angir hvor stor del av koden som er utført og dermed testet av testene. Resultatene av kode coverage uttrykkes i prosent.
Denne prosenten indikerer hvor mye av koden som er dekket av de utførte testene. For eksempel, hvis man oppnår en kode coverage på 60%, betyr det at 40% av koden ikke er testet og potensielt kan inneholde feil eller sårbarheter.
Derfor gir kode coverage en mulighet til å analysere effektiviteten og grundigheten av testene. Dette er viktig for å sikre at programvaren er testet på en tilfredsstillende måte før lansering, noe som reduserer risikoen for feil i produksjonsmiljøet som kan påvirke brukeropplevelsen negativt.
Selv om 100% kode coverage ikke garanterer at programvaren er helt fri for feil, er det et mål å strebe etter for å sikre at programvaren er grundig testet. I kritiske bransjer som romfart og medisin, hvor programvarefeil kan få fatale konsekvenser, krever regelverket ofte 100% kode coverage under testing.
Ulike måter å måle kode coverage
Det finnes flere metoder for å måle kode coverage. Disse inkluderer:
- Setningsdekning (Statement Coverage): Måler andelen av utførbare setninger i kildekoden som er utført under testing.
- Funksjonsdekning (Function Coverage): Måler andelen av definerte funksjoner som er kalt under testing.
- Gren dekning (Branch Coverage): Måler andelen av grener eller mulige stier som er utført fra alle beslutningspunktene i kildekoden. Dette sikrer at alle utfall fra kontrollstrukturer som if, switch, og if-else setninger er testet.
- Tilstandsdekning (Condition Coverage): Måler andelen av boolske uttrykk som er testet for både sanne og usanne verdier.
- Loop dekning (Loop Coverage): Måler andelen av løkker i kildekoden som er utført under testing.
- Banedekning (Path Coverage): Måler andelen av alle mulige utførelsesbaner i kildekoden som er testet.
Disse målingene blir typisk inkludert i en kode coverage-rapport.
Anbefalte fremgangsmåter for kode coverage
Definer klare coverage-mål
For alle typer programvaretesting, sett konkrete mål for ønsket coverage for hver type måling. Dette gir ikke bare klare testmål, men bidrar også til å redusere feil i programvaren ved å fokusere arbeidet på å øke kode coverage. Det bidrar også til å sikre at testing blir prioritert under programvareutviklingen.
Fokus på kvaliteten på testene
Det er viktig å merke seg at kode coverage kun indikerer andelen av koden som er testet, og ikke hvorvidt den er testet på en tilfredsstillende måte eller om programvaren er feilfri. Derfor bør man fokusere på å skrive gode og effektive tester som tester programvaren grundig, i stedet for bare å strebe etter 100% kode coverage.
Øk kode coverage i hyppig endret kode
Selv om det kan være vanskelig å oppnå høye kode coverage-tall i store prosjekter, bør man jobbe med å forbedre coverage over tid. En god tilnærming er å kreve høy kode coverage, for eksempel over 90%, for hver ny endring som legges til kodebasen.
Å håndheve kode coverage på dette nivået er realistisk og gjennomførbart, og det sikrer at alle nye endringer som gjøres i programvaren, har god testdekning.
Mål og analyser data fra kode coverage
Bruk resultatene fra kode coverage til å identifisere områder som fortsatt trenger testing, og til å prioritere fremtidige testaktiviteter. Analyser dataene for å identifisere kritiske deler av applikasjonen som ikke er testet, og rett innsatsen mot disse områdene. Dette resulterer i bedre testet programvare med færre feil.
Kode coverage kontra testdekning
Selv om begge brukes for å evaluere effektiviteten av tester, er kode coverage og testdekning fundamentalt forskjellige i deres anvendelse og hva de måler.
Testdekning er en metode som brukes for å bestemme i hvilken grad testene dekker kravene til programvaren. Dette innebærer testing av alle programvarekrav og hjelper til med å bestemme hvor godt programvaren oppfyller de definerte kravene. Testdekningsresultater presenteres som en prosentandel av testede programvarekrav, og dette arbeidet utføres vanligvis av QA-spesialister.
Kode coverage, derimot, er en testmetode som brukes for å bestemme andelen av kildekoden som er utført av testene. Resultatene av kode coverage viser i hvilken grad setninger, funksjoner, stier, løkker, grener og betingelser i kildekoden er utført av testene. Kode coverage brukes til å evaluere hvor godt testene dekker kildekoden, og utføres som regel av programvareutviklere.
Kode coverage er en viktig måling å overvåke under testing. Her er noen verktøy som kan hjelpe deg med kode coverage:
Clover
Clover er et åpen kildekode coverage-verktøy som opprinnelig ble utviklet av Atlassian, et australsk programvareselskap som utvikler produkter for programvareutvikling. Verktøyet er skrevet i Java og kan kjøres på alle operativsystemer som oppfyller kravene til Java Runtime Environment.
Clover kan brukes til å utføre kode coverage på kode skrevet i programmeringsspråkene Java, Groovy eller AspectJ. Det støtter testrammeverk som JUnit, TestNG og Spock, og det kan også integreres med IDE-er som IntelliJ IDEA og Eclipse.
Clover kan brukes til å måle coverage-målinger som metode, setning, gren, global og per-test coverage.
Etter en coverage-øvelse kan verktøyet generere tilpassbare HTML-rapporter som viser kode coverage-resultatene i tillegg til de mest risikable områdene i programvaren. Rapportene kan også genereres i PDF, XML, JSON eller ren tekst. De viktigste fordelene med Clover er at det kan integreres med mange forskjellige verktøy, og at det utvikles og forbedres kontinuerlig.
JaCoCo
JaCoCo er et gratis kode coverage-bibliotek for Java, utviklet av EclEmma-teamet. Biblioteket er implementert i EclEmma, et gratis Java code coverage-verktøy for Eclipse IDE.
JaCoCo gir en rik coverage-analyse der resultatene umiddelbart blir oppsummert og fremhevet i Java-kildekodeditoren. Dette gir brukerne muligheten til å undersøke coverage-resultatene ned til metodenivå.
Resultatene presenteres ved hjelp av et fargekodet system som fremhever kodelinjer som er helt, delvis eller ikke dekket av testene. Verktøyet gir mulighet for å slå sammen og vurdere ulike testkjøringer for å få en oversikt over total kode coverage. JaCoCo er et lett verktøy som ikke krever endringer i prosjektene dine eller annen konfigurasjon for bruk.
Cobertura
Cobertura er et gratis åpen kildekode Java kode coverage-verktøy som er basert på Jcoverage og kan brukes frittstående, via Ant-skript eller gjennom en Maven-plugin. Det vanligste er å bruke Cobertura via en Maven-plugin for kode coverage.
Cobertura måler andelen linjer eller grener som er utført av testene. Den leverer målinger som linje coverage, som viser andelen setninger som utføres under testing, og gren coverage, som viser andelen grener som dekkes. Verktøyet viser også en kompleksitetsfaktor som øker i takt med antall grener i Java-koden.
Kode coverage-resultatene presenteres i HTML eller XML, og viser hvilke deler av kildekoden som ikke er testet. I tillegg til å vise testresultater, kan Cobertura også brukes til å finne utestet kode og feil, og identifisere kode som aldri vil bli utført.
Istanbul
Istanbul er et kode coverage-verktøy for JavaScript-kode med støtte for ES6+. Verktøyet kan installeres i ethvert JavaScript-prosjekt som en utviklingsavhengighet ved hjelp av node package manager (npm).
Istanbul tilbyr coverage-målinger som setning, filial, funksjon og linje coverage. Verktøyet viser også linjer i kildekoden som ikke er dekket av testene. Dette gjøres ved å legge til linjetellere i JavaScript-koden, slik at det kan spore i hvilken grad testene utfører kildekoden.
Kode coverage-resultater fra Istanbul kan presenteres i terminalen eller som HTML. Istanbul har også støtte for applikasjoner som skaper underprosesser, og source map dekning for Babel- og TypeScript-prosjekter.
Pytest-cov
Pytest-cov er en gratis Python-plugin som brukes til å generere kode coverage-rapporter for Python-kode. Den installeres med Pythons pakkeinstallasjonsprogram (pip) og betjenes fra kommandolinjen.
Kode coverage-rapporten viser setningene i Python-prosjektet ditt, de som ikke er dekket av testene, og angir en test coverage-prosent som viser andelen av Python-koden som er dekket av tester.
Pytest-cov har støtte for underprosesser, xdist og konsistent pytest-oppførsel. Standardoppførselen til Pytest-cov er å slette eksisterende coverage-datafiler for å sikre nye og rene data for hver testkjøring. Imidlertid tillater verktøyet også brukerne å slå sammen kode coverage-testresultater fra tidligere testkjøringer.
Coverage.py
Coverage.py er et kode coverage-verktøy for Python-programmer, og det installeres i prosjekter med pip.
Verktøyet måler som standard linje- eller setningscoverage og gir resultater som viser antall setninger i programmet, de som ble oversett av tester, og prosentvis coverage. Det viser også linjer i Python-kildekoden som ikke ble testet. Coverage.py kan også konfigureres for å måle gren coverage i Python-programmer.
Coverage.py kan også brukes til å finne ut hvilke tester som utførte hvilke linjer i kildekoden. Kodedekningsrapporten kan presenteres i terminalen eller i HTML-, XML-, JSON- og LCOV-formater.
SimpleCov
SimpleCov er et kode coverage-verktøy for Ruby. Det bruker Rubys innebygde coverage-bibliotek for å samle relevante data for å bestemme kode coverage etter at tester er utført.
En av de beste egenskapene til SimpleCov er presentasjonen av coverage-resultater. Verktøyet slår også sammen resultater fra forskjellige typer tester, slik at rapporten viser resultater fra alle testene. Det gjør det enkelt å identifisere utestede deler av koden. Kildekoden er også formatert med fargekoder som gjør det lett å se testede og utestede deler av koden. Som standard måler og rapporterer SimpleCov linje coverage, men den kan konfigureres til å måle og rapportere gren coverage.
Deep Cover
Deep Cover er et nøyaktig kode coverage-verktøy for Ruby. Det gir mer nøyaktige linje coverage-rapporter ved å sikre at en linje kun regnes som dekket når den utføres fullstendig og ikke delvis.
I tillegg tilbyr Deep Cover støtte for node- og gren coverage, som kan brukes til å finne ut om det er noen grener som ikke er testet. Deep Cover er enkelt å bruke uten behov for konfigurering og kan integreres i prosjekter med andre verktøy for kode coverage, som Rubys innebygde kode coverage-bibliotek eller SimpleCov. I disse tilfellene vil Deep Cover gjøre verktøyene strengere ved å merke linjer som utført kun hvis alt på kodelinjen er fullstendig utført.
Konklusjon
Selv om høyere kode coverage ikke nødvendigvis resulterer i feilfri programvare, er det en kritisk måling som må tas med i betraktningen under testing. Kode coverage er viktig for å evaluere hvor mye av programvarens kildekode som faktisk er testet. Ved å jobbe med å forbedre kode coverage under testing, vil man få bedre testet programvare med færre feil i produksjon. For å utføre kode coverage under testing, bør du vurdere å bruke verktøyene som er foreslått i denne artikkelen.
Du kan også utforske skybaserte verktøy for lasttesting.