Kā es iemācījos mīlēt TDD

Vakar es uzstājos ikgadējā Latvijas testēšanas konferencē ar prezentāciju “How I Learned To Stop Worrying and Love Test Driven Development” jeb kā es iemācījos pārtraukt uztraukties un sākt mīlēt testu virzītu izstrādi. Tā kā auditorijai patika gan slaidi (kurus pašrocīgi zīmēju uz iPad), gan arī izraisījās diskusija par saturu, tad es šeit pārpublicēju prezentācijas kopsavilkumu.

Spējajā programmatūras izstrādē (Agile software development) testēšana nav tikai “testētāja” loma, kā tas ir bijis tradicionāli, bet gan funkcija, ko jāveic jebkuram projekta dalībniekam. Testu virzīta izstrāde (Test Driven Development, TDD) ir viena no galvenajām spējās programmatūras izstrādēs praksēm, kas tiek rekomendēta programmatūras izstrādātājiem ikdienas darbā.

TDD ideja ir ļoti vienkārša. Pirms sākt jaunas funkcionalitātes izstrādi (jauna procedūra, funkcija, metode) vispirms jūs izdomājiet, kā jūs vēlētos, lai šī jaunā programmatūras vienība strādātu – uz kādiem ievaddatiem jūs sagaidat kādus rezultātus. Un šī sagaidītā funkcionalitāte tiek aprakstīta ar automatizētu vienībtestu, kas to pārbauda. Un sākotnēji izpildot šo testu tam vajadzētu beigties neveiksmīgi, jo mums šī funkcionalitāte vēl nav izstrādāta. Tikai tad mēs sākam rakstīt programmatūras kodu, lai šo funkcionalitāti realizētu un tas tiek darīts vienkāršākajā veidā, līdz tiek panākts ka izveidotais vienībtests beidzas veiksmīgi. Un pēc tam tiek pārbaudīts, ka arī visi iepriekšējie testi izpildas veiksmīgi, lai varētu pārliecināties, ka neesam neko “salauzuši”. Veicot šādu inkrementālu izstrādi ik pa laikam tiek konstatēts, ka būtu nepieciešams uzlabot esošās programmatūras iekšējo struktūru jeb dizainu. Tad tiek veikta “refaktorēšana” – programmatūras koda struktūras jeb dizaina uzlabošana, bet netiek mainīta sagaidītā funkcionalitāte. Un to, ka netiek mainīta funkcionalitāte, var pārbaudīt izpildot visus automatizētos vienībtestus.

Šī pieeja izklausās vienkārša un loģiska un tā tiek popularizēta no Agile “guru” puses, bet realitātē šo pieeju diemžēl praktizē tikai ļoti maza programmētāju daļa. Kādēļ tas tā ir?

Tādēļ ka cilvēki pēc dabas ir slinki un vienmēr mēģina atrast iemeslus, kādēļ neko nemainīt. Šeit ir pāris tipiskie argumenti, kādēļ “tas mūsu gadījumā nestrādās”:

  • “Būs nepieciešams divreiz vairāk laika, lai uzrakstītu gan kodu, gan testus.”
  • “Mums nav laika rakstīt vienībtestus, jo termiņi jau bija vakardien.”
  • “Mums ir liels esošās programmatūras kods, ko mēs uzturam, mēs nevaram tagad uzrakstīt testus visam esošajam kodam.”
  • “Mūsu esošā programmatūra ir tā uzrakstīta, ka to nevar viegli notestēt ar automatizētiem vienībtestiem.”
  • “Mūsu klients / vadība / vēl kaut kas neļauj programmētājiem veikt refaktorēšanu, visu laiku tiek prasīta tikai jauna funkcionalitāte.”
  • “Es vienā blogā izlasīju, ka TDD īstenībā nekādus ieguvumus nedod.”

Ja jūs kaut ko nemākat, tad jums vispirms tas ir jāiemācas un tikai tad var sākt izteikt pamatotus spriedumus par to. Un jārēķinās ar to, ka mācīšanās paņem kādu laiku un jūs nebūsiet produktīvi uzreiz pirmajā dienā (arī ja jūs sevi agrāk uzskatījāt par augstas klases programmētāju, tad tik un tā pirmajā dienā jūs būsiet TDD iesācējs). Un lai kaut ko iemācītos, vispirms to vajag darīt burtiski “kā grāmatā” un tikai pēc tam var sākt eksperimentēt un pielāgot (nevis sākt ar attieksmi, ka “mums tas neder”). Un attiecībā par TDD ir pieejamas gan labas grāmatas, gan arī labi demo “screencasts” (piemēram, kā to darīt Java vai Ruby gadījumā), kas palīdz iemācīties un saprast labākās TDD prakses.

Tad, kad es šādā veidā iemācījos TDD, tad es arī sāku daudz labāk pamanīt TDD ieguvumus:

  • Lai piegādātu kvalitatīvu strādājošu programmatūru, tad līdz šim vienīgais izgudrotais veids, kā par to pārliecināties, ir testēšana. Tādēļ “netestēšana” nekad nedrīkstētu būt kā alternatīva.
  • TDD gadījumā mazāk tiek veikta atkļūdošana (debugging). Tispiski programmētāji pavada daudz laika uz atkļūdošanu, bet pēc tam kad ir panākts, ka programmatūra strādā, tad viss atkļūdošanas laikā uzrakstītais pagaidu kods tiek “izmests miskastē”. TDD gadījumā šīs atkļūdošanas kods tiek saglabāts kā vienībtesti, kas tiek automātiski izpildīti arī nākotnē, lai pārliecinātos, ka vēlāk netiek atkārtota tā pati kļūda.
  • Mazāk laika tiek patērēts uz to, lai identificētu, kurā vietā ir kļūda. TDD daudz efektīvāk palīdz atklāt tās kļūdas, kuras rodas mazu izmaiņu blakusefektu gadījumā, kuri ar manuālo testēšanu netiek identificēti (jo neviens neiedomājas, ka tur varētu būt problēma), bet automātiskie vienībtesti, kas vienmēr tiek izpildīti visi, to var atklāt.
  • TDD var un vajag izmantot arī kļūdu labošanā – atklājot kādu jaunu kļūdu vispirms tiek uzrakstīts vienībtests, kas atkārto šo kļūdu un tikai pēc tam tiek labots kods, lai atrisinātu problēmu. Šī pieeja arī noder, lai sāktu izmantot TDD esošas programmatūras uzturēšanā un jaunu izmaiņu izstrādē – sākt rakstīt testus tām vietām, kur rodas kļūdas, vai kur tiek veiktas izmaiņas.
  • Iemācoties TDD jūs saprotiet, ka tā ir projektēšanas / dizaina aktivitāte, kurai automātiskie testi ir kā papildus ieguvums. Jūs vienmēr vispirms padomājat, kāds ir funkcijas vai metodes vai moduļa nolūks un kā jūs to izmantosiet un kā jūs to testēsiet pirms jūs sākat kodēšanu, kā rezultātā TDD uzlabos jūs koda dizainu un uzturamību.
  • TDD rezultātā jūs iegūsiet arī mazāku koda apjomu, kas dara tikai to, kas patlaban nepieciešams. Un jo mazāks ir koda apjoms, jo mazāk tur būs kļūdas un jo vieglāk to būs mainīt un papildināt.
  • TDD ļauj veikt pastāvīgu refaktorēšanu un programmētājiem nevajag prasīt atļauju veikt refaktorēšanu. Ja programmas kods pastāvīgi tiks mainīts un uzlabots, tad tas visu laiku būs gatavs izmaiņām un jūs nenonāksiet līdz situācijai, kad mazu izmaiņu veikšanai būs nepieciešams ieguldīt ļoti lielu darbu dēļ tā, ka refaktorēšana tika visu laiku atlikta.
  • TDD mērķis ir visu laiku uzturēt programmatūru bez zināmām kļūdām – ja visi testi izpildās veiksmīgi, tad mums nav zināmu kļūdu. Ja tiek konstatēta jauna kļūda, tad tā ir jāatrisina vispirms, pirms tiek veikta jaunas funkcionalitātes izstrāde.

Un visu šo ieguvumu rezultātā es esmu konstatējis, ka īstenībā TDD izstrāde (ja to iemācās darīt pareizi) ir ātrāka nekā tradicionālā daļēji automatizētā, daļēji manuālā testēšana pēc tam, kad programmatūra ir izstrādāta. Kā arī kopējais patērētais laiks, lai sasniegtu kvalitatīvu rezultātu, ir mazāks.

Protams, TDD nav sudraba lode un neaizstāj visus testēšanas veidus. TDD ir efektīvs, lai notestētu, ka uz noteiktiem ievaddatiem un precīzi definēti rezultāti. Bet attiecībā uz lietotāju interfeisu ir svarīgi, vai lietotāja interfeiss labi izskatās, vai ir pareizās proporcijas un krāsu palete, vai tas ir pietiekoši vienkāršs un saprotams no lietojamības viedokļa. Uz šo aspektu testēšanu vajag izmantot cilvēkus ar atbilstošām lietojamības kritēriju testēšanas iemaņām. Bet nevajag izmantot cilvēkus kā testēšanas robotus, kas caur lietotāju interfeisu mēģina notestēt to, ko daudz efektīvāk var izdarīt ar vienībtestiem vai integrācijas testiem atbilstošā zemākā līmenī.

Programmētājiem nepatīk manuālā testēšana un “čeklistu” aizpildīšana, programmētājiem patīk kodēt. Tādēļ arī vajag palīdzēt programmētājiem iemācīt, ka testēšana ar kodēšanas palīdzību ir tikpat interesanta, kā cita veida kodēšana 🙂

11 Responses to Kā es iemācījos mīlēt TDD

  1. Arturs saka:

    Ļoti izsmeļoš teksts par TDD, kaut arī visu to zināju, man tomēr bija interesanti lasīt to. Gods un slava autoram.

  2. Labs raksts! Pilnīgi piekrītu, ka TDD ir «the way to go».

  3. aizd saka:

    1:1 kā es 😀

  4. Dīvāns saka:

    Šī bilde nav no imantas poģīša sienas?:)

  5. Ondo saka:

    Mīli citus un pats būsi mīlēts 😉

  6. Canvasway saka:

    Imantas poģītis, nopietni?

  7. Aptieka saka:

    Kas ir TDD?

  8. kred saka:

    Antra, rupja sieviete 😀

  9. Abra-kadabra saka:

    Te jau visi tādi rupji ;D

  10. Zeltaskudra saka:

    Jā, nu tur ir tā, vai nu patīk vai nē

Komentēt