Yksikkötestaus

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 23. maaliskuuta 2020 tarkistetusta versiosta . vahvistus vaatii 21 muokkausta .

Yksikkötestaus , joskus yksikkötestaus tai yksikkötestaus ( eng.  unit testing ) on ​​ohjelmoinnin prosessi, jonka avulla voit tarkistaa ohjelman lähdekoodin yksittäisten moduulien , yhden tai useamman ohjelmamoduulin joukon sekä vastaavien ohjaustietojen oikeellisuuden, käyttö- ja käsittelymenettelyt.

Ajatuksena on kirjoittaa testejä jokaiselle ei-triviaalille funktiolle tai menetelmälle. Tämän avulla voit nopeasti tarkistaa, onko seuraava koodimuutos johtanut regressioon , eli virheiden ilmaantumiseen ohjelman jo testatuissa paikoissa, ja helpottaa myös tällaisten virheiden havaitsemista ja poistamista. Voit esimerkiksi päivittää projektissa käytetyn kirjaston nykyiseen versioon milloin tahansa suorittamalla testejä ja tunnistamalla yhteensopimattomuudet.

Edut

Yksikkötestauksen tavoitteena on eristää ohjelman yksittäiset osat ja osoittaa, että osat toimivat erikseen.

Tämän tyyppisen testauksen tekevät yleensä ohjelmoijat .

Rohkaiseva muutos

Myöhemmin suoritetun yksikkötestauksen avulla ohjelmoijat voivat reagoida uudelleen ja olla varmoja siitä, että yksikkö toimii edelleen oikein ( regressiotestaus ). Tämä rohkaisee ohjelmoijia vaihtamaan koodia, koska on tarpeeksi helppoa tarkistaa, että koodi toimii edelleen muutoksen jälkeen.

Helpompi integrointi

Yksikkötestaus auttaa poistamaan yksittäisiä moduuleja koskevat epäilykset, ja sitä voidaan käyttää alhaalta ylöspäin suuntautuvaan testaukseen: ensin testataan yksittäisiä ohjelman osia ja sitten koko ohjelmaa.

Koodidokumentaatio

Yksikkötestejä voidaan pitää "elävänä asiakirjana" testattavalle luokalle . Asiakkaat, jotka eivät osaa käyttää tätä luokkaa, voivat käyttää yksikkötestiä esimerkkinä.

Käyttöliittymän erottaminen toteutuksesta

Koska jotkin luokat voivat käyttää muita luokkia, yhden luokan testaus ulottuu usein toisiinsa liittyviin luokkiin. Esimerkiksi luokka käyttää tietokantaa; kirjoittaessaan testiä ohjelmoija huomaa, että testin on oltava vuorovaikutuksessa tietokannan kanssa. Tämä on virhe, koska testi ei saa mennä luokkarajan ulkopuolelle. Tämän seurauksena kehittäjä abstraktioi tietokantayhteyden ja toteuttaa tämän rajapinnan käyttämällä omaa valeobjektiaan . Tämä johtaa vähemmän yhtenäiseen koodiin, mikä minimoi järjestelmän riippuvuudet.

Kun yksikkötestaus epäonnistuu

Monimutkainen koodi

Ohjelmistojen testaus on kombinatorinen tehtävä. Esimerkiksi Boolen muuttujan jokainen mahdollinen arvo vaatisi kaksi testiä, yksi TOSI ja toinen EPÄTOSI. Tämän seurauksena jokainen lähdekoodirivi vaatii 3–5 riviä testikoodia.

Algoritmeilla, kuten marssikuutioilla tai punamustalla puulla , on haarautunut päätöspuu, ja kaikkien vaihtoehtojen tarkistamiseen tarvitaan valtavia testisarjoja: yhdessä GitHubin punamusta puutoteutuksesta tehtiin kaksitoista testiä lisäyksen tarkistamiseksi [1] . Toisessa he rakentavat automaattisesti 10! = 3,6 miljoonaa permutaatiota ja koe ne kaikki [2] .

Kuten mikä tahansa testaustekniikka, yksikkötestaus ei salli kaikkia ohjelmavirheitä. Itse asiassa tämä johtuu siitä, että käytännössä on mahdotonta jäljittää kaikkia mahdollisia ohjelman suorituspolkuja, paitsi yksinkertaisimpia tapauksia.

Tulos tiedetään vain suunnilleen

Esimerkiksi matemaattisessa mallintamisessa . Yrityssovellukset toimivat usein äärellisten ja laskettavien joukkojen kanssa, kun taas tieteelliset sovellukset jatkuvat . [3] Siksi on vaikeaa valita testejä kullekin ohjelmahaaralle, on vaikea sanoa, onko tulos oikea, säilyykö tarkkuus jne. Ja monissa tapauksissa mallinnuksen laatu määräytyy "silmällä". ”, ja viimeinen tulos tallennetaan ”viittaukseksi”. Jos poikkeama löytyy, uusi tulos tarkistetaan manuaalisesti ja selvitetään kumpi on parempi: vanha vai uusi.

Koodi, joka on vuorovaikutuksessa järjestelmän kanssa

Koodia, joka on vuorovaikutuksessa porttien , ajastimien , käyttäjän ja muiden järjestelmän "epävakaiden" osien kanssa, on erittäin vaikea testata eristetyssä ympäristössä.

Mutta tämä ei tarkoita, että yksikkötestaus olisi täysin sopimaton tähän: se pakottaa ohjelmoijan siirtymään esimerkiksi tiedostoista ja porteista abstrakteihin virtoihin . Tämä tekee koodista yleisemmän (esimerkiksi voit vaihtaa tiedostoista verkkopistorasioihin ilman ongelmia ), testattavamman (voit tarkistaa "yhteys katkennut" -tilanteen kirjoittamalla streamin, joka simuloi onnettomuutta N tavun jälkeen; Tarkista Windows-osassa Unix- polun

Monisäikeinen

Se on pohjimmiltaan epävakaa osa järjestelmää. Lisäksi yksikkötestit ovat yleensä yksinkertaisia, kun taas monisäikeisten järjestelmien testien pitäisi päinvastoin olla melko suuria.

Integrointi- ja suorituskykyvirheet

Yksikkötestejä suoritettaessa jokainen moduuli testataan erikseen. Tämä tarkoittaa, että integrointivirheitä, järjestelmätason virheitä tai useissa moduuleissa suoritettuja toimintoja ei havaita. Lisäksi tämä tekniikka on hyödytön suorituskykytesteissä. Siten yksikkötestaus on tehokkaampaa, kun sitä käytetään yhdessä muiden testaustekniikoiden kanssa.

Yleisesti matalalla ohjelmointikulttuurilla

Yksikkötestauksen hyötyjen hyödyntäminen edellyttää tiukkaa testausteknologian noudattamista koko ohjelmistokehitysprosessin ajan. On välttämätöntä pitää kirjaa kaikista suoritetuista testeistä, mutta myös kaikista lähdekoodin muutoksista kaikissa moduuleissa. Tätä tarkoitusta varten tulisi käyttää ohjelmistoversionhallintajärjestelmää . Näin ollen, jos ohjelmiston myöhempi versio epäonnistuu aiemmin onnistuneesti läpäistyssä testissä, on helppo tarkistaa lähdekoodin muunnelmat ja korjata virhe. Sinun on myös varmistettava, että epäonnistuneita testejä seurataan ja analysoidaan jatkuvasti. Tämän vaatimuksen huomiotta jättäminen johtaa epäonnistuneiden testitulosten vyöryyn.

Ongelmia tynkäobjektien kanssa

Yksinkertaisimpia tapauksia lukuun ottamatta testattavan kohteen on oltava vuorovaikutuksessa muiden objektien kanssa. Nämä "yhteistyökumppanit" - tynkäobjektit - on tehty erittäin yksinkertaisiksi: joko äärimmäisen yksinkertaistettuja (muisti tietokannan sijaan) tai suunniteltu tiettyä testiä varten ja mekaanisesti toistava vaihto-istunto. Ongelmia voi syntyä vaihdettaessa vaihtoprotokollaa, jolloin tynkäobjektien on täytettävä uusia protokollavaatimuksia. [neljä]

Sulautetun ohjelmiston kehitys

On helppo varmistaa, että moduuli toimii kehittäjän koneessa. Vaikeampi - että kohdekoneessa, usein hyvin rajoitettu [5] .

Yksikkötestisovellukset

Extreme Programming

Äärimmäinen ohjelmointi olettaa yhtenä oletuksena automaattisten yksikkötestaustyökalujen käytön. Tämän työkalupakin voi luoda joko kolmas osapuoli (kuten Boost.Test) tai sovelluksen kehitystiimi.

Extreme ohjelmointi käyttää yksikkötestejä testilähtöiseen kehitykseen . Tätä varten kehittäjä kirjoittaa ennen koodin kirjoittamista testin, joka vastaa moduulin vaatimuksia. On selvää, että testin ennen koodin kirjoittamista ei pitäisi toimia. Jatkoprosessi rajoittuu lyhimmän tämän testin täyttävän koodin kirjoittamiseen. Kun kehittäjä on kirjoittanut seuraavan testin, koodin ja niin edelleen monta kertaa.

Yksikkötestaustekniikat

Kirjoitusyksikkötestien monimutkaisuus riippuu siitä, kuinka koodi on järjestetty. Yksittäisten entiteettien (oliosuuntautuneiden kielten luokat) vahva koheesio tai suuri vastuualue voi tehdä testaamisesta vaikeaa. Stubit tulee luoda objekteille, jotka kommunikoivat ulkomaailman kanssa (verkko, tiedostojen I/O jne.). Terminologiassa erotetaan "kehittyneemmät" tyngät - logiikkaa kantavat valeobjektit . Se on myös helpompi testata erottamalla mahdollisimman suuri osa logiikasta puhtaiksi funktioiksi . Ne eivät ole vuorovaikutuksessa ulkomaailman kanssa millään tavalla ja niiden tulos riippuu vain syöteparametreista.

On tapana erottaa testikoodi erillisiin hakemistoihin. On toivottavaa, että uusien testien lisääminen projektiin ei ole vaikea tehtävä ja että kaikki testit on mahdollista suorittaa. Jotkut versionhallintajärjestelmät, kuten git, tukevat koukkuja ( englanniksi  hook ), joilla voit määrittää kaikkien testien käynnistyksen ennen muutosten tekemistä. Jos ainakin yksi testeistä epäonnistuu, muutoksia ei hyväksytä. Myös jatkuvan integroinnin järjestelmiä voidaan soveltaa .

Toolkit

Suosituimpia korkean tason ohjelmointikieliä varten on yksikkötestaustyökaluja ja kirjastoja. Jotkut heistä:

Kielitason tuki

Joillakin kielillä on tuki yksikkötestaukselle syntaksitasolla. Tämä poistaa tarpeen valita, mihin kehykseen linkittää, ja helpottaa koodin siirtämistä muihin projekteihin.

Esimerkki tällaisista kielistä:

Koodiesimerkki D -kielellä

luokka ABC { this () { val = 2 ; } yksityinen int val ; julkinen funktio () { val *= 2 ; } } yksikkötesti { ABC a ; a . func (); väittää ( a . val > 0 && a . val < 555 ); // voit käyttää yksityistä muuttujaa moduulin sisällä }

Muistiinpanot

  1. GitHub - xieqing/red-black-tree: Red-black Tree -toteutus C:ssä . Haettu 14. huhtikuuta 2022. Arkistoitu alkuperäisestä 14. huhtikuuta 2022.
  2. http://orion.lcg.ufrj.br/java/bigjava/ch17/worked_example_2/RedBlackTreeTester.java
  3. Miksi yksikkötestit eivät toimi tieteellisissä sovelluksissa / Habrahabr . Haettu 9. kesäkuuta 2014. Arkistoitu alkuperäisestä 14. heinäkuuta 2014.
  4. Tiedon päällekkäisyyden ja vanhenemisen ongelma valeobjekteissa tai integrointitesteissä on hyvä / Habrahabr . Käyttöpäivä: 19. tammikuuta 2016. Arkistoitu alkuperäisestä 19. tammikuuta 2016.
  5. Marek Kucharski Making Unit Testing Practice for Embedded Development Arkistoitu 25. toukokuuta 2022 Wayback Machinessa

Katso myös

Kirjallisuus

  • Osherove, R. Yksikkötestauksen taito Toinen painos esimerkkien kanssa C#. - DMK Press, 2016. - ISBN 978-5-97060-415-1.

Linkit

Sivustot ja resurssit Artikkelit