De flesta som påstår sig använda TDD gör i själva verket något jag skulle kalla ”test-decorated development”: de skriver koden, den fungerar, och sedan skriver de tester för att bekräfta att den fungerar. Detta fungerar bra som ett sätt att skapa en falsk trygghet. Det är inte TDD.
Riktig TDD går till på motsatt sätt: man skriver först ett test som misslyckas, och sedan skriver man kod för att få det att godkännas. Det misslyckade testet tvingar dig att fundera över vad du egentligen vill att koden ska göra – dess publika gränssnitt, dess beteende, dess gränsfall – innan du har bestämt dig för några implementeringsdetaljer.
Men det finns ett mer subtilt misstag som även äkta tillämpare av TDD gör, och det är skillnaden mellan horisontell uppdelning och vertikal uppdelning.
Horizontal kontra Vertical är en distinktion som faktiskt spelar roll
Horizontal slicing innebär att man skriver alla tester för ett lager innan man implementerar det. Skriv alla modelltester. Skriv sedan alla servicetester. Skriv sedan alla kontrollertester. Koppla sedan ihop dem. Det låter organiserat. Det ger skräp.
Här är anledningen: när du skriver tester för en komponent isolerat innan du vet hur de andra komponenterna faktiskt kommer att bete sig, gör du antaganden. Dessa antaganden bakas in i låtsasmodeller. Låtsasmodellerna ljuger. Testerna godkänns. Integrationen är trasig. Du har spenderat en vecka på en testpyramid som inte speglar verkligheten.
Vertical slicing innebär att man tar ett beteende som är synligt för användaren och implementerar hela stacken för att få det att fungera - ett test i taget, från det publika gränssnittet och inåt. Inte ”testa all parsningslogik” utan ”testa att när en enhet ansluter och skickar en telemetriram, registrerar sessionen ett varv.” Ett beteende. Hela stacken. Fungerande och testat.
Det konkreta resultatet är att du alltid har fungerande programvara. Efter den första vertical slicen har du en funktion som fungerar från början till slut. Efter den andra har du två. Du hamnar aldrig i en situation där du har ett vackert testat datalager som inte går att använda eftersom tjänstelagret inte är klart ännu.
För agentdriven utveckling är vertical slicing inte valfritt – det är bärande. När du ger en agent ett ärende måste denne producera en fungerande, testad vertical slice. Om instruktionen är ”implementera sessionsparsningslagret” får du en hög med kod som kanske eller kanske inte integreras korrekt. Om instruktionen är ”implementera: när en session synkroniseras från en enhet ska den kunna sökas fram från sessionsskärmen” får du kod som antingen fungerar från början till slut eller misslyckas i ett integrationstest som talar om exakt varför.
Testerna blir ett avtal mellan problembeskrivningen och implementeringen. Om agentens kod klarar testerna är beteendet korrekt. Om inte är testresultatet återkopplingsslingan.