Enhedstest

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 23. marts 2020; verifikation kræver 21 redigeringer .

Unit testing , nogle gange unit testing eller unit testing ( eng.  unit testing ) er en proces i programmering , der giver dig mulighed for at kontrollere korrektheden af ​​individuelle moduler af programmets kildekode , sæt af et eller flere programmoduler, sammen med de tilsvarende kontroldata, brugs- og behandlingsprocedurer.

Ideen er at skrive test for hver ikke-triviel funktion eller metode. Dette giver dig mulighed for hurtigt at kontrollere, om den næste ændring i koden har ført til regression , det vil sige til udseendet af fejl på de allerede testede steder i programmet, og letter også opdagelsen og elimineringen af ​​sådanne fejl. For eksempel kan du til enhver tid opdatere biblioteket brugt i projektet til den aktuelle version ved at køre test og identificere inkompatibiliteter.

Fordele

Målet med enhedstestning er at isolere individuelle dele af et program og vise, at disse dele fungerer individuelt.

Denne type test udføres normalt af programmører .

Opmuntrende forandring

Enhedstest giver senere programmører mulighed for at refaktorere , mens de er sikre på, at enheden stadig fungerer korrekt ( regressionstest ). Dette tilskynder programmører til at ændre koden, da det er nemt nok at kontrollere, at koden stadig virker efter ændringen.

Nemmere integration

Enhedstest hjælper med at fjerne tvivl om individuelle moduler og kan bruges til en bottom-up tilgang til test: først test af enkelte dele af programmet og derefter programmet som helhed.

Kode dokumentation

Enhedstest kan opfattes som et "levende dokument" for klassen under test . Klienter, der ikke ved, hvordan man bruger denne klasse, kan bruge enhedstesten som eksempel.

Adskillelse af grænseflade fra implementering

Fordi nogle klasser kan bruge andre klasser, strækker test af en enkelt klasse sig ofte til relaterede klasser. For eksempel bruger en klasse en database; Mens han skriver en test, opdager programmøren, at testen skal interagere med databasen. Dette er en fejl, fordi testen ikke må gå ud over klassegrænsen. Som et resultat abstraherer udvikleren databaseforbindelsen og implementerer denne grænseflade ved hjælp af deres eget mock-objekt . Dette resulterer i mindre sammenhængende kode, hvilket minimerer afhængigheder i systemet.

Når enhedstestning mislykkes

Kompleks kode

Softwaretest er en kombinatorisk opgave. For eksempel vil hver mulig værdi af en boolsk variabel kræve to tests, en for TRUE og en for FALSE. Som et resultat vil hver linje kildekode kræve 3-5 linjer testkode.

Algoritmer som Marching-kuber eller rød-sort træ har et forgrenet beslutningstræ, og enorme testsuiter er nødvendige for at kontrollere alle muligheder: I en af ​​de rød-sort træ-implementeringer fra GitHub blev der lavet tolv test for at kontrollere indsættelse [1] . I den anden bygger de automatisk 10! = 3,6 millioner permutationer og oplev dem alle [2] .

Som enhver testteknologi tillader enhedstest dig ikke at fange alle programfejl. Dette følger faktisk af den praktiske umulighed at spore alle mulige veje til programudførelse, undtagen i de mest simple tilfælde.

Resultatet kendes kun ca.

For eksempel i matematisk modellering . Forretningsapplikationer arbejder ofte med begrænsede og tællige sæt, mens videnskabelige applikationer arbejder med kontinuerlige . [3] Derfor er det svært at udvælge tests for hver af programgrenene, det er svært at sige, om resultatet er korrekt, om nøjagtigheden opretholdes osv. Og i mange tilfælde bestemmes kvaliteten af ​​modelleringen "efter øjet" ”, og det sidste resultat registreres som “reference”. Hvis der findes en uoverensstemmelse, kontrolleres det nye resultat manuelt, og det bestemmes, hvad der er bedre: det gamle eller det nye.

Kode, der interagerer med systemet

Kode, der interagerer med porte , timere , brugere og andre "ustabile" dele af systemet er ekstremt vanskelig at teste i et isoleret miljø.

Men det betyder ikke, at enhedstest er fuldstændig uegnet her: det tvinger programmøren til at flytte fra filer og porte, for eksempel til abstrakte streams . Dette gør koden mere generel (f.eks. kan du skifte fra filer til netværksstik uden problemer ), mere testbar (du kan tjekke situationen med "tabt forbindelse" ved at skrive en stream, der efter at have udstedt N bytes vil simulere en ulykke; check under Windows-delen af ​​Unix- stikonverteringsfunktionerne

Multithreading

Det er dybest set en ustabil del af systemet. Derudover er enhedstests som regel enkle, mens tests for flertrådede systemer tværtimod burde være ret store.

Integrations- og ydeevnefejl

Når der udføres enhedstest, testes hvert af modulerne separat. Det betyder, at integrationsfejl, fejl på systemniveau, funktioner udført i flere moduler ikke vil blive opdaget. Derudover er denne teknologi ubrugelig til ydeevnetest. Enhedstestning er således mere effektiv, når den bruges i kombination med andre testteknikker.

Med en generel lav programmeringskultur

At høste fordelene ved enhedstest kræver streng overholdelse af testteknologi gennem hele softwareudviklingsprocessen. Det er nødvendigt at opbevare ikke kun registreringer af alle udførte tests, men også over alle ændringer af kildekoden i alle moduler. Til dette formål skal der anvendes et softwareversionskontrolsystem . Således, hvis en senere version af softwaren ikke består en test, der blev bestået før, vil det være nemt at kontrollere variationerne af kildekoden og rette fejlen. Du skal også sikre dig, at mislykkede tests spores og analyseres til enhver tid. At ignorere dette krav vil føre til en lavine af mislykkede testresultater.

Problemer med stubobjekter

Undtagen i de simpleste tilfælde skal objektet, der testes, interagere med andre objekter. Disse "samarbejdspartnere" - stubobjekter - er lavet ekstremt simple: enten ekstremt forenklede (hukommelse i stedet for en database) eller designet til en specifik test og mekanisk gentagelse af udvekslingssessionen. Der kan opstå problemer ved ændring af udvekslingsprotokollen, i hvilket tilfælde stubobjekterne skal opfylde de nye protokolkrav. [fire]

Indlejret softwareudvikling

Det er nemt at verificere, at modulet fungerer på udviklerens maskine. Mere vanskeligt - det på målmaskinen, ofte meget begrænset [5] .

Unit Test Applications

Ekstrem programmering

Ekstrem programmering forudsætter som et af postulaterne brugen af ​​automatiske enhedstestværktøjer. Dette værktøjssæt kan oprettes enten af ​​en tredjepart (såsom Boost.Test) eller af applikationens udviklingsteam.

Ekstrem programmering bruger enhedstests til testdrevet udvikling . For at gøre dette, skriver udvikleren, før han skriver koden, en test, der afspejler kravene til modulet. Det er klart, at testen før skrivning af koden ikke burde fungere. Den videre proces reduceres til at skrive den korteste kode, der opfylder denne test. Efter at udvikleren har skrevet den næste test, kode og så videre mange gange.

Enhedstestteknikker

Kompleksiteten af ​​at skrive enhedstest afhænger af, hvordan koden er organiseret. Stærk sammenhængskraft eller et stort ansvarsområde for individuelle enheder (klasser for objektorienterede sprog) kan gøre test vanskelig. Stubs bør oprettes til objekter, der kommunikerer med omverdenen (netværk, fil I/O osv.). I terminologi skelnes der mellem mere "avancerede" stubbe - Mock-objekter , der bærer logik. Det er også nemmere at teste ved at adskille så meget af logikken som muligt i rene funktioner . De interagerer ikke med omverdenen på nogen måde, og deres resultat afhænger kun af inputparametrene.

Det er sædvanligt at adskille testkoden i separate mapper. Det er ønskeligt, at tilføjelse af nye tests til projektet ikke er en vanskelig opgave, og at det er muligt at køre alle testene. Nogle versionskontrolsystemer, såsom git, understøtter kroge ( engelsk  hook ), med hvilke du kan konfigurere lanceringen af ​​alle test, før du foretager ændringer. Hvis mindst en af ​​testene mislykkes, vil ændringerne ikke blive begået. Kontinuerlige integrationssystemer kan også anvendes .

Værktøjskasse

Der er enhedstestværktøjer og biblioteker til de fleste populære programmeringssprog på højt niveau. Nogle af dem:

Understøttelse af sprogniveau

Nogle sprog har understøttelse af enhedstest på syntaksniveau. Dette eliminerer behovet for at vælge, hvilket framework der skal linkes til og gør det nemmere at portere kode til andre projekter.

Et eksempel på sådanne sprog:

Kodeeksempel i D- sprog

klasse ABC { this () { val = 2 ; } privat int val ; public func () { val *= 2 ; } } unittest { ABC a ; a . func (); hævde ( a . val > 0 && a . val < 555 ); // du kan få adgang til en privat variabel inde i modulet }

Noter

  1. GitHub - xieqing/red-black-tree: A Red-black Tree Implementation In C . Hentet 14. april 2022. Arkiveret fra originalen 14. april 2022.
  2. http://orion.lcg.ufrj.br/java/bigjava/ch17/worked_example_2/RedBlackTreeTester.java
  3. Hvorfor enhedstests ikke virker i videnskabelige applikationer / Habrahabr . Hentet 9. juni 2014. Arkiveret fra originalen 14. juli 2014.
  4. Problemet med duplikering og forældelse af viden i falske objekter eller integrationstests er gode / Habrahabr . Dato for adgang: 19. januar 2016. Arkiveret fra originalen 19. januar 2016.
  5. Marek Kucharski gør enhedstest praktisk for indlejret udvikling arkiveret 25. maj 2022 på Wayback Machine

Se også

Litteratur

  • Osherove, R. The Art Of Unit Testing Anden udgave med eksempler i C#. - DMK Press, 2016. - ISBN 978-5-97060-415-1.

Links

Websteder og ressourcer Artikler