Hitaat testit, tuottavuuden polonium

 
rakettitiede_jussi_pakkanen_ci_hitaat_testit_yksikkotestaaminen-2.jpeg
 
 

Hitaat testit ja CI ovat tuttu, joskin epätoivottu vieras monella työpaikalla. Yksikkötestien ajamiseen saattaa kulua puoli tuntia ja kauemminkin. Tämä on paitsi ajanhukkaa, myös masentavaa; terminaalissa rullaavan tekstin toljottaminen muuttuu äkkiä tylsäksi. Testien nopeuttaminen tuntuu kovin työläältä, eikä siihen yleensä kannusteta. Kannattaisiko? 

Jokainen softakehitystä pidempään tehnyt tietää, että yksikkötestien nopeuttamiseen kannattaa laittaa paukkuja. Ikävä kyllä tämä ei aina ole mahdollista. Syy tähän ei yleensä ole tekninen. Pikemminkin syy on se, että monissa projekteissa lopulliset päätökset resurssien jakamisesta tekee henkilö, jonka osaamisvahvuudet eivät ole itse kehitystyössä vaan jossakin muussa. Esimerkiksi numeroiden asettamisessa pysty- ja vaakariveihin. Ja päätöksien tekemiseen tältä pohjalta, vailla syvempää ymmärrystä siitä mistä asiassa oikeastaan on kyse.

Jos tällaiselle henkilölle menee ehdottamaan työajan käyttöä testijärjestelmän parantamiseen, vastaus on aina sama. "Meillä ei ole nyt aikaa käyttää tämmoiseen, meillä on ominaisuudet X, Y ja Z, jotka pitää saada valmiiksi tulipalokiireellä." Jos oikein hyvin käy, vastaus saattaa sisältää epämääräisen lupauksen, että tähän saa laittaa aikaa "joskus tulevaisuudessa, kun on vähemmän kiire". Spoilerina todettakoon, että tämä aika ei koskaan koita.

Jos havaitset olevasi tässä tilanteessa, ainoa tapa selvitä on käyttää vastustajan, anteeksi esimiehen, voimaa häntä itseään vastaan. Järkeen vetoaminen ei auta. Kokemukset muista projekteista eivät auta. Konferessiesitelmät eivät auta. Ainoa millä on väliä on taulukkolaskentaohjelmassa näkyvät numerot.

Kytkekää virta Fermi-estimaattoriin!

Oletetaan, että työskentelemme 10 hengen tiimissä. Koodin kehittämiseen käytetään Githubista tuttua prosessia, jossa kukaan kehittäjä ei saa laittaa koodia suoraan päähaaraan, vaan kaikki työ tehdään merge requestien kautta. Oletaan että yksikkötestien ajamiseen menee 30 minuuttia sekä lisäksi:

  • Itse koodaamiseen ja requestin arviointiin ei mene lainkaan aikaa (ei pidä paikkaansa),

  • CI-järjestelmä voi ajaa äärettömän monta ajoa rinnakkain (tämäkään ei ole totta),

  • yksikään muutos ei konfliktoi vaan menee kerralla sisään (erittäin ei-totta) ja

  • normaali työpäivä on 7,5 tuntia ja kaikki aika käytetään kehitykseen (tarvitseeko sanoakaan?).

Jo näin vähäisestä määrästä dataa voidaan löytää mielenkiintoisia rajoitteita. Näistä ehkä mielenkiintoisimpana se, kuinka monta muutosta koodikantaan voi ylipäänsä tehdä. Jos yhden muutoksen saaminen masteriin kestää puoli tuntia, yksi kehittäjä pystyy yhden työpäivän aikana parhaimmassa tapauksessa tekemään vain 15 muutosta. Koska miltei jokainen muutos vaatii virittämistä ja uusimista, on oikea luku noin 3–7 muutosta päivässä. Tämä on varsin hyvin verrattuna 60-luvun FORTRAN-eräajokoodaamiseen, mutta nykymaailmassa tätä voi pitää lähinnä naurettavana.

Yksinkertainen kertolasku kertoo meille, että kymmenen kehittäjää pystyy tekemään 150 muutosta päivässä. Tästä voimme helposti laskea, kuinka paljon aikaa testien kehittämiseen kannattaa laittaa. Jos testit nopeutuvat yhden minuutin, se tarkoittaa päivässä 150 minuutin ajansäästöä. Jos tämän muutoksen tekemiseen meni alle 2 ja puoli tuntia, käytetty aika on saatu tienattua takaisin yhdessä päivässä.

Vaikka jo tämä tulos on yksiselitteinen, se ei välttämättä riitä vakuuttamaan papujen laskijoita. Laajennetaan siis horisonttia kattamaan yksi kokonainen tuotesykli. Oletetaan yksinkertaistuksen vuoksi, että yhteen julkaisuun tarvitaan 1000 muutosta. Lasketaan myös, että jokainen muutos vaatii testien ajamisen kaksi kertaa: kerran kehittäjän omalla koneella ja kerran CI-järjestelmässä.

Tässä tapauksessa kokonaisaika, jonka työntekijät joutuvat käyttämään vain testien valmistumista odottaen on 30 x 1 000 x 2 = 60 000 minuuttia eli 133 henkilötyöpäivää. Tämä luku ei edelleenkään sisällä kehitystyötä, ainoastaan peukaloiden pyörittämistä testien valmistumista odotellen. 10 hengen tiimillä ja 100 % peukalonpyöritysallokaatiolla se tekee 13 vuorokautta, eli viikonloput huomioiden melkein 3 viikkoa.

Jos sen sijaan otamme yhden työntekijän pois tiimistä ja laitamme hänet vain nopeuttamaan yksikkötestejä, kuinka paljon testien pitää nopeutua, jotta siitä olisi hyötyä? Toisin sanoen kuinka paljon testeihin kuluvasta ajasta pitää vähentää, jotta 9 työntekijää joutuu odottamaan yhtä kauan kuin 10 tekijää joutuu odottamaan 30 minuutin kokonaiskestolla?

Oikea vastaus on 3 minuuttia. Jos testien ajo kestää 27 minuuttia, 9 henkilöä pystyy tuottamaan 1 000 muutosta 13 vuorokaudessa. Kunhan kymmenes henkilö saa puristettua 3 minuutin nopeutuksen kolmen viikon aikana, se olisi taloudellisesti järkevää vaikka hän viettäisi loppuajan siestaa.

Säästön voi laskea monin eri tavoin. Jos testit nopeutuvat 24 minuuttiin, kokonaisodotusaika vähenee 106 henkilötyöpäivään. Säästö on 26 henkilötyöpäivää, eli yhden henkilön kuukauden työpanos. Firman talousjohtajalta voi sitten käydä kysymässä, kuinka paljonko tämä on rahana ja kannattaako se pistää savuna ilmaan.

Jo nämä laskelmat osoittavat, kuinka testiympäristöön panostaminen kannattaa. Eivätkä ne edes ota huomioon kaikkein suurinta voittoa: säästetty aika kertautuu joka ikinen kuukausi projektin päättymiseen asti.

Ajan käyttäminen testien nopeuttamiseen ei ole ainoastaan kannattavaa, sen pitäisi olla pakollista.

Yksikkötestien nyrkkisäännöt

  • Yksikkötestit olisi hyvä saada ajettua minuutissa.

  • Yksikkötestien ajaminen ei saa missään tapauksessa kestää yli viittä minuuttia.

  • Käytä järjestelmää, joka pystyy ajamaan yksikkötestit rinnakkain.

  • Hitaat testit johtuvat usein hitaista tietokantaoperaatioista tai verkkoliikenteestä. Tee näistä yksikkötestattavat mock-versiot tai siirrä testit integraatiotesteihin.

  • Pitkään kestävien testien nopeuttamiseen laitetut panostukset maksavat itsensä nopeasti takaisin sekä säästettynä aikana että työmotivaation parantajana.

Lue myös:

Kurkistus Linuxilla pyörivän kolikkoautomaatin sisään