När skriver du den "riktiga" koden i TDD?

johnny 08/19/2017. 11 answers, 20.464 views
tdd

Alla exemplen jag har läst och sett på träningsvideor har förenklade exempel. Men vad jag inte ser om hur jag gör den "riktiga" koden efter att jag blir grön. Är det här "Refactor" -delen?

Om jag har ett ganska komplicerat objekt med en komplex metod, skriver jag mitt test och det minsta minimumet för att få det att passera (efter att det först misslyckats, Rött). När går jag tillbaka och skriver den riktiga koden? Och hur mycket riktiga kod skriver jag innan jag testar? Jag gissar att den sista är mer intuition.

Edit: Tack till alla som svarade. Alla dina svar hjälpte mig oerhört. Det verkar finnas olika idéer om vad jag frågade eller förvirrade, och kanske det finns, men det jag frågade var att jag hade en ansökan om att bygga en skola.

I min design har jag en arkitektur som jag vill börja med, User Stories, och så vidare. Härifrån tar jag de användarhistorierna, och jag skapar ett test för att testa användarhistoriken. Användaren säger: Vi har folk registrerar sig för skolan och betalar registreringsavgifter. Så, jag tänker på ett sätt att göra det misslyckas. Därmed designar jag ett provklass för klass X (kanske Student), vilket kommer att misslyckas. Jag skapar sedan klassen "Student". Kanske "Skola" vet jag inte.

Men i alla fall tvingar TD Design mig att tänka igenom historien. Om jag kan göra ett test misslyckas vet jag varför det misslyckas, men det förutsätter att jag kan få det att passera. Det handlar om design.

Jag liknar detta för att tänka på Recursion. Rekursion är inte ett svårt begrepp. Det kan vara svårare att faktiskt hålla reda på det i ditt huvud, men i verkligheten är det svåraste att veta när rekursionen "bryter" när ska man sluta (min åsikt självklart.) Så jag måste tänka på vad som slutar Rekursionen först. Det är bara en ofullkomlig analogi, och det förutsätter att varje rekursiv iteration är en "pass". Återigen, bara en åsikt.

Under genomförandet är skolan svårare att se. Numeriska och bankbokstäver är "lätta" i den meningen att du kan använda enkel aritmetik. Jag kan se a + b och returnera 0, etc. När det gäller ett system av människor, måste jag tänka mig hårdare på hur man implement det. Jag har begreppet misslyckande, passera, refactor (mestadels på grund av studier och denna fråga.)

Vad jag inte vet är baserat på brist på erfarenhet, enligt min mening. Jag vet inte hur man misslyckas med att anmäla sig till en ny elev. Jag vet inte hur man misslyckas någon som skriver i efternamn och det sparas i en databas. Jag vet hur man gör en + 1 för enkel matematik, men med enheter som en person vet jag inte om jag bara testar för att se om jag får tillbaka ett databas unikt ID eller något annat när någon skriver in ett namn i en databas eller båda eller varken.

Eller kanske det här visar att jag fortfarande är förvirrad.

5 Comments
187 hobbs 07/25/2017
Efter TDD-folk går hem för natten.
14 Goyo 07/25/2017
Varför tror du att koden du skrev inte är riktig?
2 johnny 07/26/2017
@RubberDuck Mer än de andra svaren gjorde. Jag är säker på att jag snart kommer att hänvisa till det. Det är fortfarande sorts främmande, men jag kommer inte att ge upp det. Vad du sa var vettigt. Jag försöker bara göra det meningsfullt i mitt sammanhang eller en vanlig affärsapplikation. Kanske ett lager system eller liknande. Jag måste överväga det. Jag är tacksam för din tid men. Tack.
1 Edmund Reed 07/26/2017
Svaren har redan slagit nageln på huvudet, men så länge som alla tester passerar och du inte behöver några nya test / funktionalitet, kan det antas att koden du har är färdig, bar linting.
3 Borjab 07/26/2017
Det finns en asumption i frågan som kan vara problematisk i "Jag har ett ganska komplicerat objekt med en komplex metod". I TDD skriver du dina test först så att du börjar med en ganska enkel kod. Detta kommer att tvinga dig att koda en testvänlig struktur som måste moduleras. Så komplicerat beteende kommer att skapas genom att kombinera enklare objekt. Om du slutar med ett ganska komplicerat objekt eller metod är då när du refactor

11 Answers


RubberDuck 07/27/2017.

Om jag har ett ganska komplicerat objekt med en komplex metod, skriver jag mitt test och det minsta minimumet för att få det att passera (efter att det först misslyckats, Rött). När går jag tillbaka och skriver den riktiga koden? Och hur mycket riktiga kod skriver jag innan jag testar? Jag gissar att den sista är mer intuition.

Du "går inte tillbaka" och skriver "riktig kod". Det är all riktig kod. Vad du gör är att gå tillbaka och lägga till ett annat test som forces dig att change din kod för att göra det nya testet.

Vad gäller hur mycket kod skriver du innan du testar? Ingen. Du skriver zero utan ett fel test som forces dig att skriva mer kod.

Lägg märke till mönstret?

Låt oss gå igenom (ett annat) enkelt exempel i hopp om att det hjälper.

 Assert.Equal("1", FizzBuzz(1)); 

Lätt peazy.

 public String FizzBuzz(int n) {
    return 1.ToString();
} 

Inte vad du skulle kalla riktiga kod, eller hur? Låt oss lägga till ett test som tvingar en förändring.

 Assert.Equal("2", FizzBuzz(2)); 

Vi kan göra något dumt if n == 1 , men vi hoppar över till den klara lösningen.

 public String FizzBuzz(int n) {
    return n.ToString();
} 

Häftigt. Detta kommer att fungera för alla icke-FizzBuzz-nummer. Vad är nästa ingång som kommer att tvinga produktionskoden att förändras?

 Assert.Equal("Fizz", FizzBuzz(3));

public String FizzBuzz(int n) {
    if (n == 3)
        return "Fizz";
    return n.ToString();
} 

Och igen. Skriv ett test som inte passerar än.

 Assert.Equal("Fizz", FizzBuzz(6));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    return n.ToString();
} 

Och vi har nu täckt alla multiplar av tre (det är inte också multiplar av fem, vi noterar det och kommer tillbaka).

Vi har inte skrivit ett test för "Buzz" än, så låt oss skriva det.

 Assert.Equal("Buzz", FizzBuzz(5));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    if (n == 5)
        return "Buzz"
    return n.ToString();
} 

Och igen, vi vet att det finns ett annat fall vi behöver hantera.

 Assert.Equal("Buzz", FizzBuzz(10));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    if (n % 5 == 0)
        return "Buzz"
    return n.ToString();
} 

Och nu kan vi hantera alla multiplar av 5 som inte är multiplar av 3.

Fram till den här tiden har vi ignorerat refactoring-steget, men jag ser lite duplicering. Låt oss städa upp det nu.

 private bool isDivisibleBy(int divisor, int input) {
    return (input % divisor == 0);
}

public String FizzBuzz(int n) {
    if (isDivisibleBy(3, n))
        return "Fizz";
    if (isDivisibleBy(5, n))
        return "Buzz"
    return n.ToString();
} 

Häftigt. Nu har vi tagit bort dubbelarbete och skapat en välkänd funktion. Vad är nästa test vi kan skriva som kommer att tvinga oss att ändra koden? Tja, vi har undvikit fallet där numret är delbart med både 3 och 5. Låt oss skriva det nu.

 Assert.Equal("FizzBuzz", FizzBuzz(15));

public String FizzBuzz(int n) {
    if (isDivisibleBy(3, n) && isDivisibleBy(5, n))
        return "FizzBuzz";
    if (isDivisibleBy(3, n))
        return "Fizz";
    if (isDivisibleBy(5, n))
        return "Buzz"
    return n.ToString();
} 

Testerna passerar, men vi har mer dubbelarbete. Vi har alternativ, men jag kommer att tillämpa "Extract Local Variable" några gånger så att vi refactoring istället för att skriva om.

 public String FizzBuzz(int n) {

    var isDivisibleBy3 = isDivisibleBy(3, n);
    var isDivisibleBy5 = isDivisibleBy(5, n);

    if ( isDivisibleBy3 && isDivisibleBy5 )
        return "FizzBuzz";
    if ( isDivisibleBy3 )
        return "Fizz";
    if ( isDivisibleBy5 )
        return "Buzz"
    return n.ToString();
} 

Och vi har täckt alla rimliga insatser, men hur är det med unreasonable inmatning? Vad händer om vi skickar 0 eller en negativ? Skriv dessa testfall.

 public String FizzBuzz(int n) {

    if (n < 1)
        throw new InvalidArgException("n must be >= 1);

    var isDivisibleBy3 = isDivisibleBy(3, n);
    var isDivisibleBy5 = isDivisibleBy(5, n);

    if ( isDivisibleBy3 && isDivisibleBy5 )
        return "FizzBuzz";
    if ( isDivisibleBy3 )
        return "Fizz";
    if ( isDivisibleBy5 )
        return "Buzz"
    return n.ToString();
} 

Börjar detta se ut som "riktig kod" än? Ännu viktigare, vid vilken tidpunkt slutade det att vara "orealistisk kod" och övergång till att vara "riktig"? Det är något att tänka på ...

Så kunde jag bara göra det genom att leta efter ett test som jag visste inte skulle passera vid varje steg, men jag har haft mycket träning. När jag är på jobbet är sakerna aldrig så enkla och jag vet inte alltid vad testet kommer att tvinga en förändring. Ibland ska jag skriva ett test och bli förvånad över att det redan passerar! Jag rekommenderar starkt att du blir van vid att skapa en "Testlista" innan du börjar. Denna testlista ska innehålla alla "intressanta" inmatningar du kan tänka dig. Du kanske inte använder dem alla och du kommer sannolikt att lägga till fall när du går, men den här listan fungerar som en färdplan. Min testlista för FizzBuzz skulle se ut så här.

  • Negativ
  • Noll
  • Ett
  • Två
  • Tre
  • Fyra
  • Fem
  • Sex (icke trivial multipel av 3)
  • Nio (3 kvadrater)
  • Tio (icke trivial multipel av 5)
  • 15 (multipel av 3 och 5)
  • 30 (icke trivial multipel av 3 och 5)
5 comments
3 maple_shaft♦ 07/27/2017
Kommentarer är inte för längre diskussion. denna konversation har flyttats till chatt .
40 GManNickG 07/27/2017
Om jag inte helt missförstår det här svaret: "Vi kan göra något dumt om n == 1, men vi hoppar över till den klara lösningen." - Det hela var dumt. Om du vet framsidan vill du ha en funktion som <spec>, skriv test för <spec> och hoppa över den del där du skriver versioner som uppenbarligen misslyckas <spec>. Om du hittar en bugg i <spec> så är det säkert: skriv ett test först för att verifiera att du kan träna det innan du åtgärdar det och observera testpassen efter reparationen. Men det är inte nödvändigt att förfalska alla dessa mellanliggande steg.
15 user3791372 07/28/2017
De kommentarer som påpekar de stora bristerna i detta svar och TDD i allmänhet har flyttats till chatt. Om du funderar på att använda TDD, läs chatten. Tyvärr är "kvalitet" kommentarer nu dolda bland en massa chatt för framtida studenter att läsa.
nbro 07/28/2017
Jag skulle vara mer exakt när det gäller innehållet i denna "testlista", om du ville förbättra detta svar. Jag skulle uttryckligen tala om "gränsvärden" och "klassdelning".
2 hvd 07/30/2017
@GManNickG Jag tror att poängen är att få rätt mängd test. Att skriva testerna på förhand gör det enkelt att missa vilka speciella fall som ska testas, vilket leder till att situationer inte täcks på ett adekvat sätt i provningarna, eller att i stort sett samma situation blir meningslöst täckt många gånger i testen. Om du kan göra det utan dessa mellansteg, bra! Inte alla kan göra det ändå, det är något som kräver övning.

GenericJon 07/24/2017.

Den "riktiga" koden är koden du skriver för att göra ditt testpass. Really . Det är så enkelt.

När folk pratar om att skriva det lägsta läget för att göra testet grönt, betyder det bara att din riktiga kod ska följa YAGNI-principen .

Tanken med refaktorsteget är bara att städa upp det du skriver när du är glad att den uppfyller kraven.

Så länge de test som du skriver faktiskt omfattar dina produktkrav, när de passerar så är koden fullständig. Tänk på det, om alla dina affärskrav har ett test och alla dessa test är gröna, vad mer finns det att skriva? (Okej, i verkligheten brukar vi inte ha fullständig testdäckning, men teorin är ljud.)

5 comments
44 Derek Elkins 07/24/2017
Enhetstest kan inte faktiskt omfatta dina produktkrav för till och med relativt triviala krav. I bästa fall prövar de inmatningsutrymme och tanken är att du (korrekt) generaliserar till hela utmatningsutrymmet. Naturligtvis kan din kod bara vara en stor switch med ett fall för varje enhetstest som skulle passera alla tester och misslyckas för andra ingångar.
8 Taemyr 07/25/2017
@DerekElkins TDD uppmanar felaktiga tester. Faller inte enhetstester.
6 jonrsharpe 07/25/2017
@DerekElkins Det är därför du inte bara skriver enhetsprov, och också varför finns det ett allmänt antagande att du försöker göra något, inte bara, förfalska det!
35 Derek Elkins 07/25/2017
@jonrsharpe Med den logiken skulle jag aldrig skriva triviala implementeringar. T.ex. i FizzBuzz-exemplet i RubberDucks svar (som endast använder enhetsprov), förstår det första genomförandet tydligt det bara. Min förståelse av frågan är just denna dikotomi mellan skrivkod som du vet är ofullständig och kod som du verkligen tror kommer att genomföra kravet, den "riktiga koden". Min "stora switch " var avsedd som en logisk extrem för att "skriva det minsta läget för att göra testen grön". Jag ser OP-frågan som: var i TDD är principen att undviker den här stora switch ?
2 Luaan 07/25/2017
@GenericJon Det är lite för optimistiskt i min erfarenhet :) För en, det finns människor som tycker om ett meningslöst repetitivt arbete. De kommer att bli lyckligare med en jättebrytareutgång än med ett "komplicerat beslutsfattande". Och för att förlora sitt jobb, skulle de antingen behöva någon som kallar dem ut på tekniken (och de har bättre kunskap om att det faktiskt förlorar företagets möjligheter / pengar!), Eller gör extremt dåligt. Efter att ha tagit över underhållet på många sådana projekt kan jag säga att det är lätt för mycket naiv kod att vara i årtionden, så länge det gör kunden lycklig (och betalande).

Carl Raymond 07/24/2017.

Det korta svaret är att den "riktiga koden" är koden som gör testet passerat. Om du kan göra ditt testkort med något annat än riktig kod, lägg till fler tester!

Jag håller med om att många tutorials om TDD är förenklade. Det fungerar mot dem. Ett alltför enkelt test för en metod som beräknar 3 + 8 har egentligen inget annat val än att även beräkna 3 + 8 och jämföra resultatet. Det gör att det ser ut som om du bara ska duplicera kod överallt, och att testningen är meningslöst, felaktigt extra arbete.

När du är bra på testet kommer det att informera om hur du strukturerar din ansökan och hur du skriver din kod. Om du har problem med att komma fram med förnuftiga, hjälpsamma tester, bör du noga tänka på din design lite. Ett väldesignat system är lätt att testa - vilket betyder att förnuftiga tester är lätta att tänka på och att implementera.

När du skriver dina test först, se dem misslyckas, och skriv sedan koden som gör att de passerar, det är en disciplin för att säkerställa att hela din kod har motsvarande test. Jag följer inte regelbundet den här regeln när jag kodar; ofta skriver jag test efter det faktum. Men att göra test först hjälper dig att hålla dig ärlig. Med viss erfarenhet börjar du märka när du kodar dig själv i ett hörn, även när du inte skriver test först.

4 comments
6 Steve Jessop 07/26/2017
Personligen skulle testet jag skulle skriva assertEqual(plus(3,8), 11) , inte assertEqual(plus(3,8), my_test_implementation_of_addition(3,8)) . För mer komplicerade fall söker du alltid efter ett sätt att bevisa att resultatet är korrekt, other than dynamiskt beräkna rätt resultat i testet och kontrollera jämlikheten.
Steve Jessop 07/26/2017
Så för ett riktigt dumt sätt att göra det för det här exemplet kan du bevisa att plus(3,8) har returnerat det rätta resultatet genom att subtrahera 3 från det, subtrahera 8 från det och kontrollera resultatet mot 0. Detta är så uppenbart likvärdigt med assertEqual(plus(3,8), 3+8) att vara lite absurt, men om koden som testas bygger något mer komplicerat än bara ett heltal, så tar resultatet och kontrollerar varje del för korrekthet ofta rätt tillvägagångssätt. Alternativt, något som for (i=0, j=10; i < 10; ++i, ++j) assertEqual(plus(i, 10), j)
Steve Jessop 07/26/2017
... eftersom det undviker den stora rädslan, vilket är att när vi skriver provet kommer vi göra samma misstag i ämnet "hur man lägger till 10" som vi lagde i live-koden. Så försöker testet noggrant att skriva någon kod som lägger till 10 till någonting, i testet som plus() kan lägga till 10 till saker. Vi är fortfarande beroende av de programmerare-verifierade intiala loop-värdena, givetvis.
3 Warbo 07/28/2017
Vill bara påpeka att även om du skriver test efter det faktum är det fortfarande en bra idé att se dem misslyckas. hitta en del av koden som är avgörande för vad du än arbetar med, tweak det lite (t.ex. byt ut en + med - eller vad som helst), kör testen och se dem misslyckas, ångra ändringen och se dem passera. Många gånger har jag gjort det här testet misslyckas faktiskt, vilket gör det värre än värdelöst: det är inte bara att testa någonting, det ger mig falskt förtroende för att något testas!

Victor Cejudo 07/25/2017.

Ibland kan vissa exempel på TDD vara vilseledande. Som andra har påpekat tidigare, är koden du skriver för att göra testen den riktiga koden.

Men tro inte att den riktiga koden ser ut som magi-det är fel. Du behöver en bättre förståelse för vad du vill uppnå och då måste du välja testet i enlighet med utgångspunkt från enklaste fall och hörnfall.

Om du till exempel behöver skriva en lexer startar du med en tom sträng, sedan med en massa vitrum, sedan ett tal, sedan med ett tal omgivet av blankytor, då ett felaktigt nummer etc. Dessa små omvandlingar leder dig till rätt algoritm, men du hoppar inte från det enklaste fallet till ett mycket komplicerat fall valt dumt för att få den riktiga koden klar.

Bob Martin förklarar det perfekt här .


CandiedOrange 07/25/2017.

Refactor-delen är ren när du är trött och vill gå hem.

När du ska lägga till en funktion är refactor-delen vad du ändrar innan nästa test. Du refactor koden för att göra plats för den nya funktionen. Du gör detta när du know vad den nya funktionen kommer att bli. Inte när du bara tänker på det.

Det här kan vara lika enkelt som att byta namn på GreetImpl till GreetWorld innan du skapar en GreetMom klass (efter att du har lagt till ett test) för att lägga till en funktion som kommer att skriva ut "Hej mamma".


graeme 07/27/2017.

Men den riktiga koden skulle dyka upp i refaktortrinnet i TDD-fasen. Det vill säga koden som ska vara en del av den slutliga utgåvan.

Test ska köras varje gång du gör en förändring.

Mottot för TDD-livscykeln skulle vara: RED GREEN REFACTOR

RED : Skriv testen

GREEN : Gör ett ärligt försök att få funktionskod som skickar test så fort som möjligt: ​​duplicat kod, obskurligt namngivna variabler hacks av högsta ordningen etc.

REFACTOR : Rengör koden, namnge variablerna korrekt. Torka upp koden.

5 comments
5 mcottle 07/25/2017
Jag vet vad du säger om den "gröna" fasen, men det innebär att hårdvarans returvärden så att testen går över kan vara lämpliga. Enligt min erfarenhet ska "Green" vara ett ärligt försök att göra arbetskod för att uppfylla kravet, men det får inte vara perfekt men det ska vara så komplett och "shippable" som utvecklaren kan hantera i ett första pass. Refactoring är troligen bäst gjort lite senare efter att du har gjort mer utveckling och problemen med första passet blir tydligare och möjligheter att DRY uppstår.
graeme 07/25/2017
@mcottle Jag anser att alla är en del av samma uppgift. få det gjort, rensa sedan upp det. Ytterligare refactorings bör ske som tiden går som en del av andra uppgifter.
1 Bryan Boettcher 07/25/2017
@ mcottle: du kan bli förvånad över hur många implementeringar av ett få-bara-arkiv kan vara hårdkodade värden i kodbasen. :)
6 Kaz 07/25/2017
Varför skulle jag någonsin skriva skräpkod och städa upp det, när jag kan vrida snygg produktionskvalitetskod nästan lika fort som jag kan skriva? :)
1 Kaz 07/27/2017
@TimothyTruckle Vad tar det om 50 minuter att hitta den enklaste möjliga ändringen, men bara 5 för att hitta den näst enklaste möjliga förändringen? Går vi med näst enklaste eller fortsätter att leta efter enklaste?

Timothy Truckle 07/27/2017.

När skriver du den "riktiga" koden i TDD?

Den red fasen är där du write kod.

I refactoring det primära målet att delete kod.

I den red fasen gör du något för att göra provet as quick as possible och at any cost . Du ignorerar helt vad du någonsin har hört talas om bra kodningspraxis eller designmönster. Att göra testet grönt är allt som spelar roll.

I refactoring rensar du upp den röra du just gjort. Nu ser du först om den förändring du just gjort är den typ av toppen som är mest på listan Transformation Priority och om det finns någon koddubbling kan du med största sannolikhet ta bort det genom att använda en design patter.

Slutligen förbättrar du läsbarheten genom att namnge identifierare och extrahera magic numbers och / eller bokstäver till konstanter.


Det är inte rödrefaktor, det är rödgrönt-refaktor. - Rob Kinyon

Tack för att du pekar på det här.

Så det är den green fasen där du skriver den real code

I den red fasen skriver du executable specification ...

2 comments
Rob Kinyon 07/27/2017
Det är inte rödrefaktor, det är rödgrönt-refaktor. Den "röda" är att du tar din testpaket från grönt (alla test passerar) till rött (ett test misslyckas). Den "gröna" är där du slarvigt tar din testsvit från rött (ett test misslyckas) till grönt (alla testpass). "Refactor" är där du tar din kod och gör det vackert samtidigt som alla tester passerar.
Timothy Truckle 07/27/2017
@RobKinyon Tack, uppdaterade svaret.

Robert Andrzejuk 07/27/2017.

Du skriver Real Code hela tiden.

Vid varje steg skriver du kod för att uppfylla de villkor som din kod kommer att uppfylla för framtida uppringare av din kod (som kan vara dig eller inte ...).

Du tror att du inte skriver användbar ( real ) kod, för i ett ögonblick kan du refactor det ut.

Kod-Refactoring är processen att omstrukturera befintlig datorkod - ändra factoring-utan att ändra sitt externa beteende.

Vad det här betyder är att även om du ändrar koden, kvarstår de villkor som koden satisifieras, oförändrad. Och de kontroller ( tests ) du genomförde för att verifiera Din kod finns redan för att verifiera om dina ändringar har ändrats något. Så koden du skrev hela tiden finns där, bara på ett annat sätt.

En annan anledning Du kanske tror att det inte är riktig kod, det är att du gör exempel där slutprogrammet redan kan åstadkommas av dig. Det här är mycket bra, som det visar. Du har kunskap om domain du programmerar i.
Men många gånger programmerare finns i en domain som är new , unknown för dem. De vet inte vad slutresultatet kommer att bli och TDD är en technique att skriva programmer steg för steg, dokumentera vår knowledge om hur systemet ska fungera och verifiera att vår kod fungerar så.

När jag läste boken (*) på TDD, var den viktigaste funktionen som stod ut för mig: TODO-listan. Det visade mig att TDD också är en teknik för att hjälpa utvecklare att fokusera på en sak i taget. Så det här är också ett svar på din fråga om How much Real code to write ? Jag skulle säga tillräckligt med kod för att fokusera på 1 sak i taget.

(*) "Testdriven utveckling: Genom exempel" av Kent Beck

1 comments
2 Robert Andrzejuk 07/27/2017
"Testdriven utveckling: Genom exempel" av Kent Beck

Zenilogix 07/31/2017.

Du skriver inte kod för att göra dina tester misslyckade.

Du skriver dina tester för att definiera vilken framgång som ska se ut, vilket bör alla först och främst misslyckas eftersom du inte har skrivit koden som kommer att passera.

Hela punkten om att skriva initialt misslyckade tester är att göra två saker:

  1. Täck alla fall - alla nominella fall, alla kantfall, etc.
  2. Bekräfta dina test. Om du bara ser dem passera, hur kan du vara säker på att de på ett tillförlitligt sätt rapporterar ett misslyckande när man inträffar?

Poängen bakom rödgrön refaktor är att skriva de rätta testerna först ger dig självförtroendet för att veta att koden du skrev för att klara provningarna är korrekt och låter dig refactor med förtroendet för att dina test kommer att informera dig så snart som möjligt något raster, så du kan omedelbart gå tillbaka och fixa det.

I min egen erfarenhet (C # /. NET) är rent test-först lite av ett ouppnåeligt ideal eftersom du inte kan sammanställa ett samtal till en metod som ännu inte finns. Så "test först" handlar egentligen om att koda upp gränssnitt och stubber implementeringar först och sedan skriva tester mot stubbarna (vilket först kommer att misslyckas) tills stubbarna är ordentligt flaskade ut. Jag skriver aldrig "misslyckande kod", bara bygga ut från stubbar.


Zan Lynx 07/27/2017.

Jag tror att du kan vara förvirrad mellan enhetstester och integrationsprov. Jag tror att det också kan finnas acceptanstest, men det beror på din process.

När du testat alla de små "enheterna" testar du dem alla monterade eller "integrerade". Det är vanligtvis ett helt program eller bibliotek.

I kod som jag har skrivit integrationstestet ett bibliotek med olika testprogram som läser data och matar det till biblioteket, kontrollera sedan resultaten. Då gör jag det med trådar. Sedan gör jag det med trådar och gaffel () i mitten. Sedan kör jag det och dödar -9 efter 2 sekunder, så börjar jag och kontrollerar återställningsläge. Jag fuzz det. Jag torterar det på alla sätt.

Allt detta är också test, men jag har inte en ganska röd / grön display för resultaten. Det lyckas antingen, eller jag gräver igenom några tusen rader av felkod för att få reda på varför.

Det är där du testar den "riktiga koden".

Och jag tänkte bara på det här, men kanske du inte vet när du ska göra färdskrivningstester. Du är färdig med att skriva enhetstester när dina test utövar allt du angav det ska göra. Ibland kan du tappa bort det bland alla felhantering och kantfall, så du kanske vill göra en bra testgrupp med bra sökprov som helt enkelt går rakt igenom specifikationerna.

1 comments
Peter Mortensen 07/27/2017
(dess = possessiva, det är = "det är" eller "det har". Se till exempel How to Use Its and It's .)

user3791372 07/27/2017.

Som svar på titeln på frågan: "När skriver du den" riktiga "koden i TDD?", Svaret är: "knappast någonsin" eller "väldigt långsamt".

Du låter som en student, så jag kommer att svara som om du rådgör en student.

Du kommer att lära dig massor av kodande "teorier" och "tekniker". De är bra för att passera tiden på överdrivna studentkurser, men av mycket liten nytta för dig som du inte kunde läsa i en bok på halva tiden.

Arbetet med en kodare är enbart för att producera kod. Kod som fungerar riktigt bra. Därför planerar du kodaren koden i ditt sinne, på papper, i en lämplig applikation etc., och du planerar att arbeta om eventuella brister / hål i förväg genom att tänka logiskt och sidled innan kodning.

Men du behöver veta hur du ska bryta din ansökan för att kunna designa anständig kod. Om du till exempel inte visste om Little Bobby Table (xkcd 327) skulle du förmodligen inte sanera dina insatser innan du arbetar med databasen, så du skulle inte kunna säkra dina data kring det här konceptet.

TDD är bara ett arbetsflöde som utformats för att minimera buggarna i din kod genom att skapa test av vad som kan gå fel innan du kodar din ansökan eftersom kodning kan bli exponentiellt svårare ju mer kod du introducerar och du glömmer buggar som du en gång tänkt på. När du tror att du har avslutat din ansökan kör du testerna och bommen, förhoppningsvis kommer buggar att fånga dina test.

TDD är inte - som vissa tror - skriv ett test, få det att passera med minimal kod, skriv ett annat test, få det som passerar med minimal kod osv. Istället är det ett sätt att hjälpa dig att koda säkert. Detta ideal för kontinuerlig refaktorkod för att få det att fungera med test är idiotiskt, men det är ett bra koncept bland studenterna, eftersom det får dem att må bra när de lägger till en ny funktion och de lär fortfarande sig hur man kodar ...

Vänligen fall inte ner den här fällan och se din roll att koda för vad det är - en kodares jobb är enbart för att producera kod. Kod som fungerar riktigt bra. Nu kommer du ihåg att du kommer att vara klockan som professionell kodare, och din klient kommer inte att bry dig om du skrev 100 000 påståenden, eller 0. De vill bara ha kod som fungerar. Verkligen bra, faktiskt.

5 comments
3 johnny 07/25/2017
Jag är inte ens nära en student, men jag läser och försöker tillämpa bra tekniker och vara professionell. Så i den meningen är jag en "student". Jag frågar bara väldigt grundläggande frågor eftersom det är så jag är. Jag gillar att veta exakt varför jag gör vad jag gör. Själva hjärtat. Om jag inte får det, tycker jag inte om det och börjar ställa frågor. Jag behöver veta varför, om jag ska använda den. TDD verkar intuitivt bra på vissa sätt som att veta vad du behöver för att skapa och tänka igenom saker, men genomförandet var svårt att förstå. Jag tror att jag har en bättre grepp nu.
4 Sean Burton 07/27/2017
Det är TDD: s regler. Du är fri att skriva kod men du vill, men om du inte följer de tre reglerna gör du inte TDD.
2 user3791372 07/27/2017
"Regler" för en person? TDD är ett förslag som hjälper dig att koda, inte en religion. Det är ledsen att se så många människor följa en idé så analt. Även uppkomsten av TDD är kontroversiell.
2 Alex 07/28/2017
@ user3791372 TDD är en mycket strikt och tydligt definierad process. Även om många tycker att det bara betyder "Gör några test när du programmerar", så är det inte. Låt oss försöka inte blanda upp villkor här, den här frågan handlar om processen TDD, inte allmän testning.

Related questions

Hot questions

Language

Popular Tags