Det var en tid da programmerere ble betalt av antall linjer med kode som de skrev. De ble behandlet som kildekoden som produserer maskiner som arbeider i hytter og til gengitt vurderte de programmering bare en jobb som de gjør åtte timer om dagen og så glemmer det, for resten av dagen.
Men tider har endret seg. De fleste kabinettverkene forsvant og programmører begynte å elske sin håndverk. Med fremkomsten av Agile teknikker og Programvarehåndverkbevegelsen, kom mange nye verktøy fram for å hjelpe programmereren og prosessen. TDD blir langsomt de facto-måten å skrive kode på, og hemmelighetene til SCRUM eller Kanban ble avdekket til programmene i de mørkeste hjørnene av kabinetsverdenen.
Automatisert testing og testdrevet utvikling (TDD) er noen av de grunnleggende teknikkene Agile gitt til oss programmerere. Og et verktøy som følger med disse metodene, brukes til å produsere testkode dekning, som er temaet i denne artikkelen.
"I datavitenskap er kodedekningen et mål som brukes til å beskrive i hvilken grad kildekoden til et program er testet av en bestemt testpakke." ~ Wikipedia
Definisjonen ovenfor, hentet fra Wikipedia, er en av de enkleste måtene å beskrive hvilken kode dekning betyr. I utgangspunktet har du i prosjektet en gjeng med produksjonskode, samt en gjeng med testkode. Testkoden utøver produksjonskoden, og testdekningen forteller deg hvor mye av produksjonskoden din som ble utøvet av testene.
Informasjon kan presenteres på ulike måter, fra enkle prosenter til fin grafikk eller til og med sanntidsutheving i din favoritt IDE.
Vi vil bruke PHP som språket for å eksemplifisere koden vår. I tillegg trenger vi PHPUnit og XDebug for å teste vår kode og samle dekningsdata.
Her er kildekoden vi skal bruke. Du kan også finne den i vedlagte arkiv.
klasse $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ kolonner), "); hvis ($ lastSpaceIndex! == false && substr ($ streng, $ cols, 1)! = ") return substr ($ string, 0, $ lastSpaceIndex). string, $ lastSpaceIndex), $ cols); else return substr ($ streng, 0, $ cols). "\ n". $ this-> wrap (substr ($ streng, $ kols), $ kols); returner $ string;
Koden ovenfor inneholder en enkel funksjon som bryter inn tekst til et spesifisert antall tegn, per linje.
Vi skrev denne koden ved hjelp av Test Driven Development (TDD), og vi har 100% kode dekning for det. Dette betyr at ved å kjøre testen, utøver vi hver eneste linje i kildekoden.
require_once __DIR__. '/ ... /WordWrap.php'; klasse WordWrapTest utvider PHPUnit_Framework_TestCase funksjon testItCanWrap () $ w = new WordWrap (); $ this-> assertEquals (", $ w-> wrap (null, 0)); $ this-> assertEquals (", $ w-> wrap (", 0)); $ this-> assertEquals ('a' $ w-> wrap ('a', 1)); $ this-> assertEquals ("a \ nb", $ w-> wrap ('a b', 1)); $ this-> assertEquals ("ab \ nc ", $ w-> wrap ('ab c', 3)); $ this-> assertEquals (" a \ nbc \ nd ", $ w-> wrap ('en bc d', 3));
En måte å få dekningdata på er å kjøre testene våre i CLI (kommandolinjegrensesnittet) og analysere utgangen. For dette eksempelet antar vi et UNIX-lignende operativsystem (Linux, MacOS, FreeBSD, etc). Windows-brukere må tilpasse banene og kjørbare navn, men det skal være ganske like.
La oss åpne en konsoll og endre kataloger i din test
mappe. Kjør deretter PHPUnit
med mulighet til å generere dekningsdata som ren tekst.
phpunit --coverage-text =. / coverage.txt ./WordWrapTest.php
Dette bør fungere ut av boksen på de fleste systemer hvis XDebug er installert, men i noen tilfeller kan det oppstå en feil relatert til tidssoner.
PHP Advarsel: dato (): Det er ikke trygt å stole på systemets tidszoneinnstillinger. Du er * påkrevd * for å bruke date.timezone-innstillingen eller date_default_timezone_set () -funksjonen. Hvis du brukte noen av disse metodene, og du fortsatt får denne advarselen, har du sannsynligvis feilstavet tidssoneidentifikatoren. Vi valgte tidssone UTC for nå, men vennligst sett date.timezone for å velge tidssone. i phar: ///usr/share/php/phpunit/phpunit.phar/ PHP_CodeCoverage-1.2.10 / PHP / CodeCoverage / Report / Text.php på linje 124
Dette kan enkelt løses ved å angi den foreslåtte innstillingen i din php.ini
fil. Du kan finne måten å angi tidssone i denne listen. Jeg er fra Romania, så jeg vil bruke følgende innstilling:
date.timezone = Europa / Bucharest
Nå, hvis du kjører PHPUnit
kommandoen igjen, bør du ikke se noen feilmeldinger. I stedet blir testresultatene vist.
PHPUnit 3.7.20 av Sebastian Bergmann ... Tid: 0 sekunder, Minne: 5.00Mb OK (2 tester, 7 påstander)
Og dekningsdataene vil være i den angitte tekstfilen.
$ cat ./coverage.txt Kode Dekningsrapport 2014-03-02 13:48:11 Sammendrag: Klasser: 100,00% (1/1) Metoder: 100,00% (1/1) Linjer: 2,68% (14/522) WordWrap Metoder: 100,00% (1/1) Linjer: 100,00% (7/7)
La oss analysere dette litt.
wordwrap
er vår eneste klasse.pakke inn()
metode, ingenting annet.wordwrap
. Hver seksjon har egne metoder og linjedetaljer. Basert på disse observasjonene kan vi konkludere med at vår kode er 100% dekket av tester. Nøyaktig som vi forventet før analysen av dekningsdataene.
Ved å bare endre en enkel parameter for PHPUnit, kan vi generere fin HTML-utgang.
$ mkdir ./coverage $ phpunit --coverage-html ./coverage ./WordWrapTest.php
Hvis du sjekker din ./dekning
katalog, vil du finne mange filer der. Jeg vil ikke lime inn listen her fordi den er ganske omfattende. I stedet vil jeg vise deg hvordan det ser ut i en nettleser.
Dette er ekvivalent med oppsummeringsdelen fra tekstversjonen ovenfor. Vi kan zoome inn ved å følge de foreslåtte koblingene og se flere detaljer.
De tidligere eksemplene var interessante og de er ganske nyttige, hvis Koden din er bygd på en ekstern server som du bare har SHH eller nettilgang til. Men det ville ikke vært fint å ha all denne informasjonen, bor i IDE?
Hvis du bruker PHPStorm, er alt innenfor avstanden til et enkelt klikk! Velg for å kjøre testene dine med dekning og all informasjon vil bare bare dukke opp, magisk.
Dekningsinformasjonen vil være til stede i IDE, på flere måter og på flere steder:
Med et så kraftig verktøy i utviklerens hender og under ledelsens nese, var det uunngåelig for noen myter å overflate. Etter at programmererne nektet å bli betalt av antall kodelinjer de skriver, eller ledere innså hvor lett det er å spille systemet, begynte noen av dem å betale programmerere med prosentandelen av kodedekning. Høyere kode dekning betyr programmerer var mer forsiktig, ikke sant? Det er en myte. Kode dekning er ikke et mål på hvor godt du skriver kode.
Noen ganger har programmerere en tendens til å tro at kode med 100% dekning ikke har noen feil. En annen myte. Kode dekning bare forteller deg at du har testet hver linje av kode. Det er et mål på antall linjer som utøves. Det er ikke et mål på antall linjer som er riktig implementert. For eksempel vil halv skriftlige algoritmer med bare halvdefinerte tester fortsatt ha 100% dekning. Dette betyr ikke at algoritmen er ferdig eller at den fungerer riktig.
Endelig er spillingen systemet veldig enkelt. Selvfølgelig, hvis du bruker TDD, har du naturligvis en høy dekning verdi. På hele prosjekter er 100% umulig. Men på små moduler eller klasser er det svært enkelt å skaffe 100% dekning. Ta for eksempel vår kildekode og forestill deg at du ikke har noen tester i det hele tatt. Hva ville være den enkleste testen for å utøve all koden?
funksjon testItCanWrap () $ w = new WordWrap (); $ this-> assertEquals ("a b \ nc", $ w-> wrap ('a b c', 3)); $ this-> assertEquals ("a \ nbc \ nd", $ w-> wrap ('en bc d', 3));
Det er det. To påstander og full dekning. Dette er ikke det vi ønsker. Denne testen er så langt fra beskrivende og fullstendig at det er latterlig.
Kode dekning er en statusindikator, ikke en enhet for å måle ytelse eller korrekthet.
Kode dekning er for programmerere, ikke for ledere. Det er en måte å oppdage problemer i vår kode. En måte å finne gamle, uprøvde klasser på. En måte å finne stier som ikke utøves av testene som kan føre til problemer.
På virkelige prosjekter vil kode dekning alltid være under 100%. Å oppnå perfekt dekning er ikke mulig, eller hvis det er, er det sjelden et must. For å ha 98% av dekning må du imidlertid målrette 100%. Å ha noe annet som målet ditt er ikke-sanselig.
Her er koden dekning på Syneto's StorageOS konfigurasjonsprogram.
Totalt er det bare ca. 35%, men resultatene trenger tolkning. De fleste modulene er i det grønne, med mer enn 70% dekning. Men det er en enkelt mappe, Vmware
, som trekker ned gjennomsnittet. Det er en modul med mange klasser som bare inneholder definisjoner for kommunikasjons API. Det er ingen grunn til å teste disse klassene. De ble generert automatisk av klarert kode. Programmene vil vite dette, og de vil vite hvordan de skal tolke resultatene. En leder kan insistere på å teste den fordi den er en rød linje og det ser mistenkelig ut for noen som ikke kjenner til de interne detaljene i prosjektet. Ville det være noe fornuftig å teste det? Ikke i det hele tatt! Det ville være en ubrukelig test, som ville ta opp dyrebare titalls sekunder med byggetid uten noen fordel.
Så her er hvor vi er med kode dekning: Det er et flott verktøy for programmerere, en kilde til informasjon for å markere mulige problemer, en misforstått virkelighet for de fleste ledere, og et annet verktøy for å tvinge og måle programmerernes aktiviteter. Som med ethvert annet verktøy, er det en som kan brukes riktig og misbrukes enkelt.