Vinkit testivetoisen kehityksen kanssa tasapainotteluun
Meillä Sysartilla on pitkät perinteet testivetoisen kehityksen (TDD, test-driven development) soveltamisesta asiakasprojekteissa. TDD:ssä kantava idea on kirjoittaa vaatimuksia vastaavat testit ensiksi, sitten testit läpäisevä koodi ja lopulta refaktoroida koodi hyväksi tuotantokoodiksi.
Maailma on muuttunut paljon siitä kun TDD:stä ruvettiin puhumaan lähes 20 vuotta sitten. Modernissa webbikehityksessä parhaat tavat testata ovat yleensä varsin erilaiset, mutta esimerkiksi integraatioprojekteihin TDD sopii edelleen hyvin. Vuosien varrella on myös opittu paljon siitä, mitä asioita testivetoisessa kehityksessä tulee käytännössä varoa tai huomioida.
TDD:n pohjalta on kehitetty myös erilaisia tekniikoita tuoda asiakas mukaan osaksi määrittely- ja testausprosessia. Näistä esimerkkinä BDD (Behavior-driven development) ja ATDD (Acceptance test-driven development). Tässä jutussa keskitytään kuitenkin itse TDD:hen, jossa testit tehdään puhtaasti kehittäjän näkökulmasta.
Testikirjaston paisuminen ennustaa ongelmia jatkokehitykselle
Toteutetun projektin jälkeen näyttää monesti hyvältä: meillä on toimiva tuotantokoodi ja sille kattava testisetti. Pienet muutokset ja korjaukset onnistuvat todennäköisesti helposti.Ongelmia helposti tulee, kun testit kirjoittanut kehittäjä lähtee projektista. Ymmärtävätkö uudet ylläpitäjät mitä testit tarkalleen testaavat? Hajoavatko testit, kun toteutetaan uusia featureita? Voikin olla että testien omaksumiseen ja ylläpitoon menee paljon enemmän aikaa kuin itse koodin.
Vinkit TDD:n tehokäyttöön
Testaa järjestelmän käyttäytymistä
TDD:n tärkeimpänä ohjenuorana on testata järjestelmän käyttäytymistä eikä sisäisen toteutuksen yksityiskohtia. Jos tässä onnistutaan, testit hajoavat vain vaatimusten muuttuessa. Tässä kantavana ajatuksena on, että jos ohjelmisto toimii ulospäin oikealla tavalla, toimii myös sisäinen toteutus. Sisäisessä toteutuksessa voi toki olla ongelmia, mutta ne ovat luonteeltaan sellaisia, ettei niitä olisi saatu yksikkötesteillä kiinni alkuunkaan (esimerkiksi suorituskykyongelmat, muistivuodot).Mikä yksikkö?
Yksikkötestauksessa yksikkönä ajatellaan helposti ohjelmointikielen luokkaa, mutta juuri tämä johtaa edellä mainittuihin ongelmiin. Ajattelemalla toteutettavaa moduulia tai vaatimusta yksikkönä (mikropalveluiden tapauksessa ehkä koko palvelua), päästään luonnollisesti siihen, että testataan laajempaa kokonaisuutta.Poista testejä
Kehittäessä voi olla tarpeen testata nimenomaan toteutuksen yksityiskohtia, jotta saa kaiken kohdalleen. Tällaisia testejä saa toki kirjoittaa, mutta tämän jälkeen tulisi miettiä palveleeko testi sovelluksen ylläpitäjää vai hankaloittaako jatkokehitystä. Mikäli päätyy jälkimmäiseen, tulisi testi poistaa rohkeasti.Pidä yksinkertaisena
Testejä kirjoittaessa on houkutus käyttää hienoja tekniikoita, joilla itse sovelluksen toimintaa voidaan matkia mahdollisimman pitkälle (mocking). Nämä ovat kuitenkin omiaan lisäämään testien kompleksisuutta. Vanha ja buginen testikirjasto on ylläpitäjän painajainen. Mieti siis mikä on yksinkertaisin tapa testata toteutettava vaatimus.
Aiheesta muualla:
https://martinfowler.com/articles/is-tdd-dead/ (2014)
https://www.youtube.com/watch?v=EZ05e7EMOLM (2016)