www.solita.fi solita@solita.fi TDD Käytännössä Todellinen työkalu vai lehmipoikien laukkaa? Harri Kulmala Solita Oy 1
TDD Käytännössä Test Driven Development yleisesti Lupaukset Esimerkki Projektin ja menetelmän yhteensopivuus Lupausten lunastus Test Driven Development Pragmaattinen lähestymistapa ohjelmistosuunnitteluun TDD on hybridi suunnittelu- ja toteutusvaiheista suunnitellaan pienissä palasissa voi korvata up-front -suunnitteluvaiheen Liittyy XP-metodologiaan, mutta ajatukset sovellettavissa prosessista riippumatta Teknologiariippumaton Java,.NET, Python,... 2
Periaatteet Pohjana järjestelmän käyttötapaukset ja vaatimukset Jokainen muutos testataan Edetään pienissä paloissa Virheettömyys Lupaukset 100% testikattavuus, bugiton järjestelmä Yksinkertainen arkkitehtuuri KISS-periaate Ylläpidettävyys muutosten aiheuttamat ongelmat havaitaan välittömästi Ennustettavuus koodi on todella valmista silloin, kun se on valmista 3
Vaatimukset Itsekuri Työkalut Kokemus Motivaatio Prosessi: Kädet saveen 1. Tee testi 2. Aja testit, varmista, että uusi testi epäonnistuu 3. Tee pieni muutoskoodiin 4. Aja testit, varmista, että kaikki onnistuvat 5. Refaktoroi, poista copy/paste koodi Keskity yhteen asiaan kerrallaan, kirjaa kaikki muut mieleentulevat muutokset tai ideat todo-listaan 4
Esimerkki Vaatimus: Numeroluokka, joka osaa yhteenlaskun 1. Tehdään testi, varmistetaan että se epäonnistuu Esimerkki Vaatimus: Numeroluokka, joka osaa yhteenlaskun 1. Tehdään testi, varmistetaan että se epäonnistuu 2. Tehdään pieni muutos, jolla testi saadaan toimimaan 5
Esimerkki Vaatimus: Numeroluokka, joka osaa yhteenlaskun 1. Tehdään testi, varmistetaan että se epäonnistuu 2. Tehdään pieni muutos, jolla testi saadaan toimimaan 3. Refaktoroidaan, poistetaan copy/paste 4. Jatketaan kohdasta 1, kunnes lopputulos tyydyttää Testikattavuus 100% Mitä meillä on? Joukko automatisoituja regressiotestejä koska sääntönä on, että uuden ominaisuuden lisääminen vaatii uuden testitapauksen, on testeissä myös sisältöä 6
Virheettömyys Testikattavuus koko ajan 100% Onko silti testattu kaikki tarpeellinen? Mihin asti testausta pitää jatkaa? Entä järjestelmän osien välinen integraatio ja sen testaaminen? Järjestelmätestaus? Toiminnallinen testaus? Skaalautuvuus ja suorituskyky TDD ei poista muiden testausvaiheiden tarvetta Yksikkötestit korvataan (lähes?) täydellisesti Lähtökohta on toiminnallisuudessa Yksinkertainen arkkitehtuuri Pääpaino on ominaisuuksien, vaatimuksien ja käyttötapausten ajattelussa Arkkitehtuuri on juuri niin yksinkertainen, kuin toiminnallisuus vaatii Luotetaan refaktorointiin 7
Ylläpidettävyys Arkkitehtuuri on yksinkertainen Regressiotestit ovat kattavat ja automatisoidut Muutosten vaikutusten arviointi helpottuu ja nopeutuu Testitapaukset dokumentoivat luokkien käyttötavat laajemmin kuin metodidokumentaatio toimivat informaation lähteenä kehittäjien välillä Ennustettavuus Kun koodi on valmista, se on todella valmista Ei kuitenkaan sinällään auta arvioimaan sen tarkemmin etukäteen, kuinka suureksi työmäärä muotoutuu 8
Hopealuoti? Hankalat asiat Testaaminen on edelleen vaikeaa vaatii osaamista ja kokemusta Kaikkia vaatimuksia ei ole mahdollista pukea suoraan testitapauksiksi täytyy muistaa, että ne on kuitenkin puettava tekniseksi toteutukseksi Joskus testien teko vaatii hyötyyn nähden kohtuuttoman työmäärän tai ainakin näyttää vaativan Kurinalaisuudesta tinkiminen johtaa nopeasti rappioon testikattavuus saattaa olla silti 100% 9
Päättelyketju 1. TDDataanpas tämä meidän sovellus! 2. Jaha, tässä on webbiui:ta, monisäikeisyyttä, ja tietokanta 3....aikaa kuluu... 4....aikaa kuluu PALJON... 5. Webbiui:ta ei kannata testata, liikaa työtä. Tietokantaa on järjetöntä lähteä testaamaan, ja monisäikeisyyttä on paha pukea testitapauksiksi 6. Hävittiin aikaa ja rahaa, ei enää koskaan TDD:tä! Asioita, joita on hankala testata Tietokantaintensiiviset operaatiot Käyttöliittymät Servletit/J2EE Riippuvuudet Monisäikeisyys, ajastetut operaatiot 10
Asioita, joita on hankala testata Tietokantaintensiiviset operaatiot Käyttöliittymät Servletit/J2EE Riippuvuudet Kokemus Työkalut Työkalut Kokemus Monisäikeisyys, ajastetut operaatiot Kokemus Case: Projekti X Suurehko (yli 150 KLOC) Siirtyi toisesta organisaatiosta ylläpidettäväksi ja jatkokehitykseen Lähdettiin tutustumaan järjestelmään testitapausten avulla Ongelmia yksikkötesteissä: Suurin osa oli kiireessä tekaistu Osa ei testannut mitään, ajoi vain koodin Testattavaa yksikköä ei oltu eriytetty ympäristöstään 11
Osaamisen siirto Kirjoitettiin kriittisten komponenttien osalta yksikkötestit uudelleen eriytys ympäristöstä pala kerrallaan rakennettiin testitapauksia hankalien asioiden testaamiseen etsittiin keinoja testauspatterneista tarvittaessa refaktoroitiin Osaamisen siirron tulokset Prosessin aikana (tuotannossa olevasta komponentista) paljastui n. 30 ennen löytymätöntä virhettä jälkikäteen tehtyyn testaukseen upposi iso työmäärä voidaan ajatella kuitenkin, että ensimmäinen testauskierros oli hyödytön: olisiko TDD-ajatuksia seuraten päästy samaan työmäärään on myös vaikea arvioida paljonko nuo löytymättömät virheet olisivat aiheuttaneet ylläpitotyötä testaaminen hyvin suoraviivaista, ojankaivuutyötä Testaukseen kannatti panostaa 12
Jatkokehitys #2 Osa uusista komponenteista toteutettutddperiaatteella yksittäisten kehittäjien vastuulla Vuoden mittaisen inkrementaalisen kehitystyön aikana on raportoitu keskimäärin yksi virhe/kompontti Virheitä muualla järjestelmässä on löytynyt kumulatiivisesti kymmeniä Miten maailmalla Chrysler ja portaaliprojekti: ensimmäisen version aikana 1 raportoitu virhe kuukaudessa toisen vuoden aikana 1 raportoitu virhe, tuolla ajanjaksolla uusi versio + useita välitoimituksia Thoughtworks kehittäjätalo, perustaa toimintansa XPmetodologiaan varovainen arvioissaan, mutta ns. huipputiimit pääsevät 1 bugi/kk tahtiin 13
TDD:n ominaisuuksia Voi olla yksittäisen kehittäjän työväline vaatimuksena on joka tapauksessa kattavat yksikkötestit, joten miksi ei sopisi? Voi myös olla projektiryhmän yhteinen menetelmä suurimmat tehonlisäykset löytyvät tästä Yhteensopiva minkä tahansa prosessin kanssa ei sinällään ota kantaa erillisen suunnitteluvaiheen tai muiden vaiheiden olemassaoloon Millainen projekti Vaatimukset ja ominaisuudet selkeitä voidaan hajoittaa osakokonaisuuksiin Teknologia-alue tuttu ei sovi prototyyppikehitykseen kovin hyvin Uusi projekti, vanhan ylläpito vain uusien ominaisuuksien osalta arkkitehtuurissa tulee ottaa huomioon testattavuus Projektin koko ei sinällään vaikuta 14
TDD ei automaattisesti takaa mitään......mutta oikeissa käsissä on hyvä mahdollisuus, että testit ovat olemassa testit ovat keskimääräistä kattavampia testit mittaavat oikeita asioita muutokset ovat hallittavissa järjestelmä on suunniteltu testattavaksi TDD pakottaa ajattelemaan testausta ja testattavuutta. testausta ei voi vain sivuuttaa TDD ei toimi ainakaan, jos... Projektiryhmä ei ole motivoitunut sen käyttöön luovuutta on vaikea pakottaa menetelmää on helppo syyttää Työkalut eivät ole ajan tasalla ei helpotusta vaikeiden asioiden testaamiseen Tavoitteista lipsutaan TDD:ssä on olennaista, että TDD-prosessia seurataan hyvin kurinalaisesti 15
Tehokkuus Optimaalisestikin onnistuneessa projektissa täytyy muistaa, että varsinaisen koodaamisen osuus kokonaisuudesta on varsin pieni lähteestä riippuen n. 20-40% Työmäärä ei välttämättä alene, mutta tavoitteena onkin parempi laatu Worst-case -skenaario Projektin loppuvaiheessa Kattavuus sallituissa rajoissa (yli 80%), mutta testit ovat rispaantuneet ja toimivat vain osittain Tekninen dokumentaatio kokonaan hajanaisten testitapausten sisällä Testien teko työlästä, jatkuvaa virittelyä Järjestelmä ei toimi, virheitä edelleen vanhaan malliin Ominaisuuksien toteutuksessa on menty siitä mistä aita on matalin, jotta testaus ei olisi liian työlästä 16
TDD Yhteenveto parhaimmillaan tarjoaa ylläpidettävyyttä, automaattiset regressiotestit ja robustisuuden ei poista prosessia hyvän kehittäjän soveltamana erinomainen menetelmä ei välttämättä jokaiseen projektiin tai tarkoitukseen TDD menetelmänä ei ole vaikea, mutta onnistunut testaaminen on edelleen haaste Itsekuri, osaaminen, motivaatio ja oikeat työkalut Lähdemateriaalia Kirjoja Test Driven Development: By Example, Kent Beck JUnit Recipes, J.B. Rainsberger Test-Driven Development in Microsoft.NET, James W. Newkirk Refactoring: Improving the Design of Existing Code, Martin Fowler Web http://testdriven.com http://c2.com/cgi/wiki?testdrivendevelopment Agile software development: www.agilealliance.com 17