London Style TDD aka Mockist Approach

No Gravatar

GothPy User Group Logotype

Igår huserade Göteborgs Python-användargrupp, GothPy, i Squeeds lokaler och temat för kvällen var “London Style TDD“. En annan term som också använts för samma(?) stil eller variant av TDD är Mockist approach. För dem av som sitter i en statiskt/starkt typad, kompilerad miljö, tycker jag att detta är en teknik man skall förstå och gärna behärska – för varje software craftsman (eller kanske software crafts-hen) så bör detta vara en teknik eller ett verktyg bland flera, det är ett ganska tydligt tillvägagångssätt som används för att mejsla fram mjukvara.

Vi var dryga dussinet, åt många ovanligt små pizzor från Pizza Hut och hade oväntat mycket diskussioner kring mycket: jag hade väntat mig mindre diskussion och mer kodande. Jag tyckte dock det var mycket hög nivå på diskussionerna och många bra sidor och argument lyftes fram, vilket jag tror hela gruppen upplevde eftersom det var få som uttryckte någon önskan att “de ville gå vidare”. Lite oväntat för mig var den klart intressanta och underhållande dissektionen av klassificering av Test Doubles (alltså vad är egentligen dummies, stubs, fakes, spies, mocks?). Utan att gå in på detaljer så tog jag med mig en något rubbad uppfattning om klassisk TDD jämfört med mockbaserad TDD (classic vs stubborn).

Före

Mina två huvudsakliga åsikter som jag hade med mig in i rummet var de följande.

Klassisk = tillståndsbaserad testning, Mockbaserad = beteendebaserad

Jag är av uppfattningen att mängden testkod i ett icke-trivialt system kommer vara lika stor oavsett om man kör klassisk eller mockbaserad stil.

Den “stora” skillnaden är att fake-implementationerna behöver vara tillräckligt tillståndsfulla för att tillåta inspection så att man kan stämma av tillstånd i testens assertions. Dessutom behöver fake-implementationerna uppfylla beteendedelen av de kontrakt som finns. I starkt typade språk (Java) innebär det inte sällan komplicerade implementationer för att kunna nå gränsfall, eller multipla fake-implementationer.

Med mockbaserade test-doubles är tillstånd aldrig intressant och därför har man “bara” en aspekt att bry sig om när man skriver sina test doubles – beteende-/kontraktsaspekten.

Detta blir intressant i fallet när kodbasen rör på sig, gränssnitt och beteenden förändras. Med fake-implementationer behöver man ändra beteenden + sin tillstånds-implementation (som behövs för att kunna göra asserts på sluttillstånd) så att den fortfarande matchar originalets beteende. Med mock-implementationer behöver man “bara” ändra beteenden.

(Borde det inte kunna bli mindre kod rent av med mockning då, om man nu inte behöver lagra state någonstans? Jo, det kan man ju tycka från argumentationen ovan, men det inte var jag har kunnat se. Radmässigt blir möjligen testen i klassisk stil något kortare (man behöver inte välja mockarnas beteenden – fake-implementationernas default-beteenden är nog för de flesta test), men å andra sidan hamnar mer kod i test double-implementationerna.

Självklart underhåller man sin testkod med samma kärlek och omsorg som produktionskod, vilket gör att stubbning av mockobjekt – i större system – hamnar i “MockFactories” där man placerar återanvänd kod. Jag förordar inte stilen där varje mocks beteende skall uttryckas explicit i varje test – “self containing test”. Jag ser inte varför man skall lita mer på kod som ligger i test doubles av typen fake, jämfört med av typen mock. (Det argumentet låter som skrock och rädsla för det okända: “jag litar mer på min kod i min fake, än på mockito-ramverket” t ex.

I Python är behovet av mockramverk mycket litet

Min bild har varit att eftersom alla objekt är “kontraktslösa”, i meningen att allt är löst typat (Duck typing), därför gör det billigt* att skapa test doubles av olika slag, när de behövs, där de behövs och på det sätt de behövs.
I Java-språket med stark typning måste man skicka objekt som uppfyller kontrakt, medan enhetstest sällan har behov av fullvärdiga implementationer och än mindre utnyttjar enheten under test (SUT) hela, eller ens stora delar av, kontrakten från sina collaborators i enskilda test.

Efter

Ett bra argument jag själv helt förbisett (vilket är en klar hint om hur ofta jag jobbar med Python) är att ett bra mockramverk kan ge bra feedback när man utvecklar (“Expected %s invocations of %s, got %s”) vilket ju rättfärdigar nyttan med ett mockningsramverk.

Stubbar man mockobjekt, eller definierar man kontraktuella beteenden hos sina collaborators under viss interaktion (ett tests livscykel) med följande kod:

when(collaboratorA.reserveSeats(10)).thenThrow(new RuntimeException("database is down"));
// or
when(collaboratorA.cancelReservation("1234")).thenReturn(new ReservationCancellation());

En terminologigrej tror jag – jag har inte använt ordet stub utan använt andra formuleringar (förbereder, “berättar för mockobjektet hur det ska bete sig” t ex).

Jämför med BDDMockito-smaken:

given(collaboratorA.reserveSeats(10)).willThrow(...);
// or
given(collaboratorA.cancelReservation("1234")).willReturn(...);

En annan sak jag vill fundera mer på var rekommendationen att inte mocka 3pp, “don’t mock what you don’t own” tror jag var originalfraseringen. Den diskussionen gick lite för fort för mig och ambitionen att “bara lägga på ett till lager” mellan plattformens eller 3pp-ramverkets API:er och det man själv vill använda minimerar möjligen kontaktytan (och framtvingar ett mer explicit ställningstagande i hur beroende man vill vara av 3pp-saken), men flyttar i viss mån bara runt problemet till det nya lagret.

Bevis

Nej, det finns givetvis inte. Kod är i stora delar ett hantverk och då är världen sällan skalan svart eller vit.

Jag började för ett litet tag försöka skriva ett exempel på hur kod kan se ut med mockbaserad teststil, jämte klassisk stil. Dock inte i Python. Jag är en bit från “klar”, exemplet är inte heller perfekt men jag tror intentionerna synas i det som finns där nu. https://github.com/FredrikWendt/tdd-classic-vs-mockist/tree/master/src/test/java/se/wendt/tdd

Slutsats

GothPy är en härlig samling med trevliga och mycket kompetenta människor från ganska varierande och olika bakgrund. Mixen är klockren och ger alltid härligt nyanserade diskussioner med högt i tak och genuin vilja att utforska olika riktningar och synsätt.

Pga denna gruppdynamik kände jag att det fanns mycket mer att fundera kring, testa (koda) och gräva i på detta ämne och jag åkte hem på vagnen utan att känna mig riktigt “färdig”! :-)

* Billig kod är lätt att läsa, förstå (lagom kort och koncis) och underhålla. Den kräver också mycket lite kognitiv belastning hos läsaren.

Fantastisk utvecklarvår i Göteborg 2012!

Aldrig förr har utvecklarcommunityn i Göteborg varit så sprudlande som den är nu, iaf om du frågar mig! Till att börja med har vi minst tre rejäla konferenser, tyvärr inte fyra då Nordic Ruby går av stapeln i Stockholm i år. Hur som helst – ovanpå det har vi ju javaforum, nforum och alla user groups på Meetup, liksom SweNug, Alt.net, OWASP och en mängd andra aktiviteter som t ex Göteborgs Agilister och allt som anordnas av DataFöreningen Sverige (DFS).

Att vi har detta utbud i Göteborg tycker jag är kanon! Det ger varje utvecklare en möjlighet att välja själv, att inte bara vara tvingad till att stirra blint på en leverantörs erbjudanden, bara en teknik, bara en grupp – dvs inte bara smalna av och ramla in i “samma gamla hjulspår”, utan verkligen har en möjlighet att bredda sin insikt, kompetens och sitt nätverk.

Det som är än mer glädjande är att i all denna “konkurrens” så har verkligen de flesta user grupper jag varit i kontakt med satt just utvecklarna i första rummet. Det finns ett litet undantag som sätter sina egna ekonomiska intressen före utvecklarna i user groupen och försöker kontrollera informationen som når utvecklarna, istället för att låta medlemmarna själva bestämma vad de tycker. Jag gissar att detta blir uppenbart så småningom och att en ny grupp bildas spontant – som är till primärt för utvecklare, inte ett bolags ekonomiska intressen.
(Min uppfattning är att utvecklare är intelligenta, självständiga individer som är helt kompetenta nog att ta egna informerade beslut, inte få “så här skall du tycka och göra” nedtryckt i halsen. Nåväl, det lär som sagt självregleras inom tid.)

Så, without further ado: här är min lista på vårens toppar i Göteborg 2012!

Konferenser

WebCoast, 16-18 mars, Lindholmen Science Park (en unconference)
Software Passion Summit, 19-20 mars, Clarion Hotel Post (Centralstationen)
Scandinavian Developer Conference, 16-17 april, Svenska mässan (Korsvägen)
dev:mobile, 12 juni, Folkets hus (Järntorget)

User Groups etc

(Dessa har ju återkommande möten och byter emellanåt plats – därav blir datum/adress inte så intressant.)

PyDev: Pythonutvecklingsmiljö

PythonPyDev är baserad på Eclipse, funkar väldigt bra för det jag gör, vilket i princip är att försöka jobba på samma sätt med Python-kod som med Java (TDD-ish = få ut kod i jämnt flöde och refactor för att få det fint).

Vid dagens diskussioner kring tools och miljöer på GothPyCon ][ så gjorde jag följande anteckningar (“konferensen” hölls på engelska) över features jag förväntar mig i en IDE:

  • graphical, remote debugging
  • virtual environments
  • syntax highlighting
  • unit test integration with coverage
  • auto completion
  • indentation
  • inline documentation
  • refactoring
  • easy navigation

Allt detta – förutom debugging – demonstreras i en fem-minuters demo på PyDevs hemsida, ihop med de tangentbindningar som är “speciella” för PyDev:

Shift+Alt+n
Shift+Enter
Ctrl+2, r
Shift+Alt+a
Ctrl+F9
F12
Ctrl+F11
Ctrl+Alt+l
Shift+Ctrl+Alt+m
Ctrl+Alt+↓↑
Alt+↓↑
alt+→

Java störst under 2011 enligt Ohloh

I denna mätning, som baserar sig på de repositorier som Ohloh bevakar, är Java det mest committade språket. Vet inte om justering görs pga dess pratighet också? Mätvärdena är relativa (procent), hade varit kul att se om C-kodsbidrag faktiskt gått ner, eller om det bara är de andra som ökat (och därmed tar större del av kakan).

Data från Ohloh

Data från Ohloh

Scandev on Tour, Stockholm 2011

Jag var iväg på Scandev on tour i Stockholm och hade en bättre dag än väntat. Huvudattraktionen för mig att åka dit som deltagare var pga Gojko Adzic: jag ville se om han verkligen är så vattentät som han verkar!

Key Note, Bruce Eckel

Dagen började med kort introduktion av Emily Bache som lämnade över till Bruce Eckel. Han feluppskattade tyvärr sin tid och missade den stora poängen med sin presentation, vilket var väldigt synd. Oklart varför han missade så grovt då det enligt egen utsago var fjärde gången han höll denna presentation. I princip så pratade han om språk och vad nästa stora språk bör ha för egenskaper. Han petade flera gånger på brister i Python, Java och C++ (nämnde inte C# en enda gång enligt mina anteckningar). CoffeeScript med jQuery förekom i hans bilder mot slutet och dessutom i koden som presenterades.

Kul med en lite mer teknisk key note! Hans egna tavlor som bakgrundsbilder till presentationerna var möjligen gav dock emellanåt för kass kontrast mot texten. Hans budskap var helt OK men jag måste säga att presentationen i sig var rätt beige.

Ruby on Rails, Shay Friedman

Jag gick sedan till Shay Friedmans presentation om Ruby on Rails. Det var antligen den mest politiskt inkorrekta presentationen under dagen (konferensen saknar för övrigt code of conduct och/eller ett manifest). Med minsta marginal snublade han nog över på rätt sida gränsen till godtagbart.

Jag hade föredragit dubbla tempot och något som stack ut från “my first 5 minutes”-spåret, kanske kika lite under huven och få se något intressant. Shay använde dock 3.1 vilket är rykande färskt med SCSS och CoffeeScript medskeppat som “standard”. Klart inspirerande och skall jag bygga sidbaserad webb (eller måhända JSON-backend) så ligger detta varmt till hands. Stort minus för att han inte körde testen en enda gång … Det hade bland annat undvikit hans två felsteg: att försöka ladda applikationen innan databasen var uppdaterad.

WCF Future

Detta var fullständig slöseri med tid, tyvärr. “You might have heard of web sockets, it’s w3c standard …”

Visualize Quality, Gojko Adzic

Efter lunchen kom dagens höjdpunkt. Gojko Adzic började lite före utsatt tid med att fiska bland publiken (han kände väl till svenskars fåordighet som åhörare) kring vad folk förväntade sig för att så småningom komma igång och helt enkelt presentera ett ganska ofärdigt material med tankar kring vad kvalitet är.
Gojko menade att t ex code quality aldrig är oviktigt, men det är inte lika viktigt i förhållande till att ett system uppfyller ett eller flera affärsvärden. David Harvey föreslog att föredragets ämne borde varit “Visualize Value” vilket jag instämmer i.

Innehållet var i övrigt bra presenterat, väl underbyggt och genomtänkt (mannen är riktigt vattentät) och ämnet hade jag snarare sammanfattat såhär:

To remove stake holder’s need for visibility (they ask for control) we need undisputibale visualization (of metrics).

Han gav exempel på tre P:n som är traditionella kvalitetsmätpunkter: Process effectiveness (such as code quality); Product status; Product Performance (have we delivered something that is actually used by users?). Han gav också förslag på andra sätt att hitta och visualiser mätvärden: Low tech testing dashboard, Risk/Test heat maps and charts, effect maps, Attribute-component-capability charts.

Intressant, framför allt bra presenterat och det föreslagna lär – rätt genomfört – otvetydigt ge bra underlag för diskussion och insyn i den egna verksamhet.

Long Term Value of Acceptance Test, Gojko Adzic

Var egentligen skåpmat och handlade om att inte dokumentera flöden i test, utan att med hjälp av smart marknadsföring (för att få stake holders intresserade) genom specification workshops få till kör- och testbar dokumentation av affärsregler, dvs företagets verksamhet. Han pekade ut TextTest som ett bra verktyg som steg i rätt riktning – dvs separera dokumentationen (testet) från det som behövs för att göra det kör-/testbart (scriptet, systemstart etc). Presenterades på ett bra och oklanderligt sätt, rubricerades som Living documentation vilket tydligen skall vara accepterbar benämning även i biznizkretsar.

Verktygstips: Relish, Speclog och Concordion.

Code Debt, David Harvey

Jag åkte på att ställa upp som försökskanin och parprogrammerade fem rader JavaScript med David Harvey. (Egentligen tror jag att jag skrev kanske femton tecken pga ovana vid Mac+eng tangentbord men men :)

David visade i alla fall på ett konkret exempel av hur kod kan evolvera fram i två riktningar – en som är lätt att arbeta med (den jag fick utöka) och en som hade en mindre positiv utveckling (Jörgen Lundberg åkte på denna elakare version och gav kommentaren: Wow). Presentation var helt OK. Den kunde varit bättre genom att fokusera mer på konkreta tips och åtgärder (eller strategier) än att belysa problemet.

Akka, Jonas Bonér

Jonas visade på vad Akka erbjuder – lösningar på problemen concurrency, scalability och fault-tolerance (that self-heal). En av lösningarna på desa problem är Akkas Actor. Detta “mönster” presenterades, med – min min smak – lite för enkla exempel. Ping-pong och self.reply("Hi " + name) funkar visserligen bra – det är lätt att läsa på en vägg med stor text – men det ger alltid lite extra när presentatören visar produktionskod och tar exempel från verkligheten.
För att hantera del av clustringen används gossip (som ger eventual consistency).

Sammanfattningsvis

Allt i allt var den dag över förväntan. Folkets Hus var kanon som lokal och allt flöt på kanon med mat och annat. Jag saknar dock open space eller någon form av mer inbjudande deltagande – i Göteborg fanns 2010 fish bowl som gör eventet till lite mer än bara “an eyes forward event” (som Bruce Eckel själv använde som benämning i sin key note).