TDD, må det være så vanskelig?

Hei. Dette er et innlegg i “frustrert utvikler” og “Er dette et tabu å snakke om?” kategorien

Jeg har laget en god del rails apper. Men, jeg har et problem med testing. Som regel har jeg kniven på strupen. Kunden vil ha ting ferdig så fort som mulig. Derfor har jeg ikke jobbet mye med TDD, selv om jeg vet det er viktig og smart.

Jeg erfarte det senest sist jeg oppgraderte en app til rails 3.1. Du verden så fint det hadde vært å ha tester da.

Så, da jeg fikk inn et oppdrag for noen uker siden tenkte jeg NÅ skal også jeg kjøre TDD og bli sikkelig proff.

Jeg satte meg godt til rette med min gode venn Ryan Bates, mekket denne

group :test do
gem "factory_girl_rails"
gem "capybara"
gem "guard"
gem "guard-rspec"
gem 'rb-fchange'
gem 'rb-notifu'
gem 'win32console'
gem 'spork', '~> 0.9.0.rc'
gem 'guard-spork'
end

og satte igang.

For det første er har jeg masse problemer med oppsettet. Det at jeg kjører Windows 7 gjør det antagelig ikke enklere.

For det andre er testene utrolig trege. Hvis jeg skipper spork, tar en test runde med 2 tester 40 sec.

Nå har det gått en uke. Siden burde vært 70% ferdig, men jeg bruker halve dagen på å finne ut hvordan jeg tester ting med en bruker innlogget ( Hvordan jeg kan lage en session i factory_girl ).

Jeg begynner å lure på om TDD er verdt alt arbeidet. Jeg kan teste i nettleseren på mye kortere tid enn det tar meg å lage testene. Jeg er uansett ikke sikret mot bugs. Hvis jeg kan glemmer å teste noe i nettleseren, kan jeg jo glemme å lage en test også.

Kan dere dele deres tanker om dette? Er det en myte at alle, alltid tester?

Vist 308 ganger. Følges av 12 personer.

Kommentarer

Problemet er at du er uerfaren til å teste, ikke at testing er vanskelig i seg selv. Det er også viktig å skille mellom TDD og automatisert testing, du er ikke nødt til å bruke TDD for å automatisere testene dine.

Etter et par prosjekter går det like fort for deg å skrive ned og automatisere testene dine som det gjør å utføre dem manuelt. Da går alt plutselig MYE fortere igjen. Du trenger bare å utføre (les: skrive ned) en test en gang. Neste gang du tester det samme, kjører du bare testen du skrev ned tidligere. Masse tid spart, masse kjedelig trykking spart, og ikke minst er datamaskinen din flink til å huske å kjøre alle testene dine, ikke bare testene for den delen av appen du driver med akkurat nå.

Jeg er klar over at det er min kunnskap som er problemet. Jeg regner likevel med at jeg ikke er den eneste som sliter med å finne tid til å lære meg dette.

Hvis jeg har et problem i alle andre deler av en rails app finner jeg svar på nettet med enkelhet. Når jeg har problemer med testing finner jeg stort sett lite. Det må jo tyde på at det slurves med dette av mange.

Jeg er innstilt på å takle dette.

Generelt
Hvilke verktøy bruker du når du tester?
Hvordan kan jeg få mine tester til å gå fortere. Jeg har prøv med spork for å hindre at rspec laster hele appen hver gang likevel sitter jeg å venter i opp i mot et minutt før testene er kjørt?

Spesielt
Hvordan sjekker man at en bruker er innlogget i rspec/Captbara?

Jeg kjenner meg veldig godt igjen i den frustrasjonen, og det tok lang tid før jeg ble komfortabel med å skrive tester, og før nytteverdien ble stor.

Jeg jobber kun TDD i visse situasjoner, og jeg fokuserer kun på de testene som gir meg nytteverdi.

TDD-biten kombinerer jeg ofte med unit-tester. Unit-testene mine er veldig kjappe å kjøre (jeg har et eget oppsett for disse), og de sparer meg for masse tid. Det tar bare et sekund fra jeg har skrevet koden, til jeg kan kjøre testen, mye kjappere enn å åpne nettlesere eller kjøre tyngre programmer.

Jeg bruker Selenium RC til integrasjonstestene. Jeg har da full tilgang til databasen, samtidig som jeg får resultatet fra nettleseren. Jeg fokuserer da på enkle innholdssjekker, utfylling av skjemaer, redirects, sjekker HTTP-kodene som returneres etc.

Jeg lager også gjerne tester til gammel kode. Ved å angripe gammel kode fra et testperspektiv, har jeg ofte oppdaget helt nye ting, og avdekket alvorlige og dyptliggende feil.

+1 for alle poengene til August. Det er idealet. Et par tanker til:

TL;DR: Tester er en investering. Du blir flinkere over tid. Noen ting er vanskeligere enn andre. Det er en fordel å kunne velge ulike approacher. Du må velge hvor du skal investere mest effort.

1. Det er ikke en all-or-nothing sak. Du kan øke testdekning over tid i små inkrementer når du ser hvor det gjør mest vondt. Man kan/må vurdere hvor man skal legge kruttet – hvor er det mest payoff ved å ha høy testdekning.

2. Noen automatiserte tester er viktigere/mer bang for buck enn andre. Jeg tenker generelt på testing som “maslows behovspyramide”

Bonus: Selenium/webtester/blackbox
Very nice to have: Functional/GUI tests
Important: Integration tests
Must-have: Domain/core unit tests

…men noen prosjekter har krav/scope som stokker om på disse prioriteringene. :)

3. Du kan vurdere hvilken TDD-apprach som funker best for deg, det er flere veier til Rom avhengig av prosjektet og dine preferanser. Utforsk mockist vs classical TDD (jeg liker classical approachen med så lite tilstand/interaksjon som mulig men mocks har sin plass og jeg burde nok vært flinkere/mer dreven til å mocke/stubbe)

4. BDD/Cucumber/outside-in funker bedre for noen folk/prosjekter enn andre. Jeg liker å jobbe bottom up med klassiske små unit tester istedet. Men hvis BDD/eksekverbare specs/ passer deg, prosjekt og/eller kunden godt så kanskje du heller bør gjøre det.

Eksperimenter med ulike approacher, aksepter at det er gråsoner og ikke føl deg mislykka hvis du ikke har så fine tester/dekning som de tøffeste software craftsmanship evangelistene. Viktigste er at man tenker aktivt på det og hele tiden blir litt bedre/får flere verktøy i skuffen ;)

Disclaimer: Disse er bare mine meninger. Jeg har praktisert automatisert testing siden 2002… men burde lære mer. Jeg skriver automatiserte tester for mange av prosjektene mine… men ikke alle. Jeg liker å jobbe strikt TDD… men gjør det ikke alltid. Jeg liker i utgangspunktet Uncle Bobs synspunkter… men synes det er drøyt å si at du ikke er profesjonell hvis du ikke har 100% testdekning.

(Hilsen mr. wishy-washy-diplomat Thomas)

Flott at du tar opp temaet! Tror mange med deg stiller seg samme spørsmålet, det er helt legitimt.

Det er ganske mange bøker skrevet om temaet: Clean Code, Growing object-oriented software guided by tests, RSpec-boka og mange fler. Felles handler de om å skrive god kode. Gode kode lar deg jobbe og endre raskt også i fremtiden, alle kan hacke opp noe veldig kjapt her og nå, med det vil forkrøple prosjektet. Tester er også kode! Derfor må testkoden være minst like god som resten av koden, den må følge DRY, SRP osv også. Mange ser på TDD/BDD som et høyere stadie i software craftsmanship.

For å si det enkelt:
Jeg vil ikke overta, bidra på eller se noe som helst kode som ikke har bra tester. Tester gjør at jeg heller refaktorerer/endrer enn dupliserer. Testene vil redde meg om jeg brekker noe som tidligere fungerte. Uten tester er duplisering er tryggere, du brekker ikke allerede eksisterende funksjonalitet, men det gjør appen stadig vanskeligere å endre.

Her har du en person som elsker kode, gode kode. Han snakker om
raske tester i railsapp

Den anbefaler jeg å se! Den handler om ekte enhetstester, som bidrar til fantastisk god kode. Den inspirerte meg.

Jeg tror du har favnet for vidt, det ser jeg i Gemfile din, derfor smerter det så mye også. Gode kommenater fra Thomas, August og André, dette er tydeligvis noe som engasjerer! Lykke til :)

Jeg har delt frustrasjonen til Andreas. Tester i Rails kjører tregt, og dobbelt så mye på Windows. Etter å ha hatt en hyggelig erfaring med JUnit og en deprimerende erfaring med Rails og tester, la jeg som TDD-infisert utvikler Rails (og Ruby) på hylla i nesten et års tid. Jeg vil faktisk heller ha et støvete språk med raske tester og rask feedback (pro-tip: vi bruker ikke Spring), enn et deilig språk med treeeege tester.

Jeg kom tilbake til Rails for et hobbyprosjekt (smidig2011.no) for noen måneder siden. Jeg oppdaget da at det tok mindre tid å installere Ubuntu og kjøre testene der en gang enn det tok å kjøre testene en gang under Windows. Eller, nesten, da.

Og selv under Ubuntu foretrekker jeg, kremt, et støvet programmeringsspråk med rask feedback.

YMMV, one hopes!

Johannes: Hovedproblemet her er vel at appen er treig å starte. Løsningen er å kode så mye logikk som mulig uten å depende på rammeverket, og ha et eget test:fast e.l. target som kjører tester som ikke depender på Rails. Det tror jeg vil være en god idé for flere aspekter av appen enn testene… Men har ikke gjort mye av dette selv. Annet enn å notere meg at Rails-tester ofte er så treige at det å praktisere TDD mot en Rails-app er nesten nytteløst, eller ihvertfall litt frustrerende.

Her var det liv!

Det er utrolig deilig å se at jeg ikke er den eneste som kjenner på frustrasjonen. Samtidig blir jeg oppmuntret til å lære meg dette bedre.

@Andre Selenium RC ser ut til å være et bra sted å begynne. Jeg kan generere tester med Selenium IDE og eksportere dem til rspec. Det ser enkelt ut. Hva slags opplegg har du for unit-testene?

@Thomas Det ser ut til at top level testing er riktig for meg. Hvis jeg har gode innholdsjekker vil jeg fange opp problemer i model filene. Jeg kan jo for eksempel teste valideringer med en top level test.

@Ole Morten Jeg så den videoen da du tipset om den for en tid tilbake. Det er veldig inspirerende og det er en veldig god investering å lære seg /venne seg til å code med mer klasser og mixins. Problemet hittil i mitt programmeringsvirke er at pengene ligger å lage nettsider med forholdsvis enkle apper, kjapt. Med tre barn og gårdsbruk med sju dårlige hus er det vanskelig å rettferdiggjøre (og lære seg å skrive) vakker kode. Men, jeg vet det er dårlige unnskyldninger og prøver nå å klatre litt.

@Johannes og @Christian Testene i rails på min maskin går noe inni H… sakte. Prøver litt unit- testing nå. Fra jeg starter testen tar det 1 minutt til testen starter. Selv jeg skriver mye kode på et minutt!

@Alle Tusen Takk for svar!

@andreas jeg glemte å si at jeg jobber i PHP hovedsakelig, så de kjappe unit testene mine kjøres der. Har dessverre ingen Rails-tips. :(

Johannes: testing i ruby går svineraskt! Men opplasting og testing av tredjepartsbiblioteker kan gå fryktelig tregt.
Rails er 3dj part og har egne tester. Hvorfor tester vi den hver gang? Les: Dropp rake og alt annet som elsker å laste opp alt mulig skit. Rydd unna miljø i spec_helper eller lag ny katalog. spec_fast.

:)

Konge at du sitter på et gårdsbruk og progger, Andreas. digger jeg! Hvor? Hvorfor? :)

@Ole Morten Hvor: Spydeberg 45 minutter fra Oslo inn i Østfold. Hvorfor: Jag trivs best i upna landskap. ( og det er utrolig deilig å sette seg på en traktor med p2 i øra og bare pløye engang i bland)

Jeg skulle gjerne ha sett flere kode eksempler på teknikken til Corey Haines.

Finnes noen gode blogger eller åpne githup repos?

Når han svarer på spørsmål på slutten sier han at controllerene ikke skal snakke med active record. Slik jeg forstår ham vil han helst ikke bruke finds eller save i controllene. Hvordan gjør han det og hvorfor? Går det raskere?

Jeg er (dessverre) mer en rails progger enn en ruby progger. Jeg kan rails bra, men må hele tiden inn i ruby docs når jeg går litt utenfor malen. Jeg ble veldig inspirert av en annen video med Corey Haines sjekk…
Å øve på ruby som om man skulle spille gitar gir mening for meg.

Jeg har vært i samme båt som deg Andreas. Test drevet utvikling er noe som har kommet de siste årene, og som jeg nå ikke klarer meg uten. Jeg har laget apps uten tester tidligere, og ettersom tiden går og kompleksiteten øker blir det en app man vegrer seg for å endre/forbedre fordi sikkerhetsnettet ikke er der, og man er livredd for å ødelegge noe. Selvsikkerheten din vil vokse med en god test-base.

Her er hva jeg ville gjort for for å komme igang, ved å følge gitar analogien:

Velg en gitar med nylonstrenger som er lett å spille på
Bruk rspec. Det er veldig godt dokumentert og det er skrevet mye om det. Med rspec kan du skrive tester for model, controller, view, routes med mer. Det er stort sett det verktøyet du trenger.

Lær de enkleste grepene
Start enkelt slik at det ikke tar over for all gleden og produktiviteten din. F.eks. lag en test-fil per model, og en per controller. Lag tester for de mest komplekse modell-metodene. Og en enkel test per controller#action. Bare her har du nå sørget for å avdekke en mengde feil som kan dukke opp, bare ved å la rspec være innom filene dine. Det er utrolig hvor mange låter du kan spille med bare E, A og D grep. Legg på C G og F, så er du jo en trubadur.

Etterhvert som du får gjort dette noen ganger vil du lære nye måter å bruke rspec på, og testen dine blir kortere og bedre. På litt sikt vil det gå av seg selv og du vil begynne å bruke rspec til å beskrive hva koden din skal gjøre før koden kommer, da er du i TDD-land. La TDD komme gradvis med at du blir bedre på testing.

Boka du bør starte med: The RSpec Book av David Chelimsky.

En kjapp innføring til å starte med rspec:

Lag et nytt rails prosjekt. Putt dette i gemfile og kjør bundle install; rails generate rspec:install;

group :test, :development do
gem "rspec-rails", "~> 2.6"
end

Du kan se mer på rspec repoen.

Når det er installert kan du kjøre en vanlig rails scaffold kommando. Her vil rspec nå henge seg på og produsere noen tomme tester. Controller testene som lages er derimot allerede montert i enkleste forstand. De kan du lese og lære av. Etterhvert som det kommer i blodet skriver du testene først.

En investering i dette vil gi deg mer tid på traktoren og med barna på sikt, så det er vel verdt det.

@Christian Hager Tusen takk for et veldig fin svar. Jeg skal prøve din fremgangsmåte. Går testene dine kjapt?

Jeg kjørte komandoen

$ rspec

og fikk

Finished in 60.99 seconds
10 examples, 3 failures, 6 pending

Det er greit hvis man bare skal kjøre testene engang i blant, men til TDD holder det ikke.

Det er sikkert noe feil med oppsettet mitt, men etter mange søk finner jeg ikke svar.

Det virker som om du har problemer med oppsettet. Du skal kunne kjøre hundrevis av tester på den tiden…

Om du ikke klarer å endre oppsettet til å fungere, altså window + ruby, så bruk windows installeren til ubuntu og få linux inn parallel. Ruby er mye bedre (og raskere) å jobbe med i linux. Eller enda bedre, kjøp en mac. Jeg jobbet først med windows, deretter med linux på en windows maskin og de siste årene på mac. Jeg liker mac miljøet best, men linux var også bra. Windows er jeg ikke glad i når det kommer til å bruke det som utvikler platform.

Hei Andreas,

Morro at du fortsatt er like ivrig! Sliter med testinga selv, har kjørt på old school testing litt for lenge. Men er i gang med å automatisere litt nå. Ikke noe tvil om at det er veien å gå:)

Hei Torbjørn!

Det var lenge siden.

Ja det er veien å gå.

Jeg anbefaler også The RSpec Book som er nevnt over. Den ga en av de beste innføringene jeg har vært borti på å arbeide med TDD.

Ellers så kan jeg anbefale screencastene til Gary Bernhardt destroyallsoftware. Det er en jeg jobber sammen med som omtaler disse som “rails porn” (yes, they’re that good).

Der går han i dybden på mange aspekter av god test design, hvordan få raskere tester (uten spork m/venner) og hvordan du kan bruke smerte i testingen til å oppdage dårlige design valg man har gjort, og hvordan drive design inn i bedre retninger i små steg.

Jeg kom over disse i sommer og har abonnert siden da ($9 i måneden som jeg betaler så gledelig!). Siden jeg begynte å ta ibruk noen av ideene har jeg fått en del små øyer av kode som har bedre design og raskere tester.

Når jeg jobber med noe som er ren logikk lager jeg nesten alltid en vanlig ruby klasse for det, og kjører testene for bare den klassen mens jeg jobber. Da er det ihvertfall fort nok til at jeg ikke får pause i tenkingen mens jeg jobber med selve businesslogikken. Så kan jeg kjøre alle testene når jeg er klar til å sjekke inn.

Da ser det som oftest ut som noe slik:

...........

Finished in 0.24839 seconds
11 examples, 0 failures

Når jeg er så heldig at jeg har en sånn bit med kode å jobbe med hender det jeg gjør som Corey Haines og kjører testene to ganger på rad fordi de går så fort :)

Nye bilder