For at teste et system skal du isolere bivirkninger

At tage bivirkninger ud er en af ​​de bedste måder at opbygge testbar kode

Billedet af en boksekamp mellem to mandlige krigere. Deres ansigter er uden for rammen. Fighter til venstre har sendt en venstre krog til jagerfly i højre side. Kampen til højre bærer en rød kort med et lille symbol på Sovjetunionen.

Nock er et berømt bibliotek skrevet i JavaScript, der er nyttigt til at stoppe netværksanmodninger. Det returnerer et statisk svar for testene, så de kan køre, selvom en HTTP-server ikke er tilgængelig.

Men det er også en lugt.

Den resulterende kobling mellem datakilden og systemet under test er en omkostning, der kan påvirke kodens refactoring og vedligeholdelighed.

Her er hvorfor.

Lad os sige, at der er en server, der returnerer en liste over indlæg og en funktion, der forbruger svaret fra den server til at oprette en liste over indlægstitler. Testen til funktionen bruger Nock til at stoppe svaret fra serveren:

Et diagram, der viser en blok til venstre med overskriften

Koden har anstændig dækning. Der er dog nogle problemer med det.

Hvis du foretager ændringer i svarets indholdstype, skal du ændre testene, selvom kodens opførsel forbliver den samme:

Det samme gælder, hvis du foretager ændringer af URL, overskrifter eller parametre, som Nock stopper. Du skal ændre testene, selvom systemets opførsel forbliver den samme:

Funktionen "Opret liste over indlæg" er System Under Test (SUT). Dataene fra HTTP-opkaldet er datakilden.

Du kan designe koden, så datakilden har en generel grænseflade, der kan sættes til SUT. I dette tilfælde kan du udøve logikken uden behov for for meget opsætning.

Et diagram, der viser en blok til venstre med overskriften

I et testmiljø kan du injicere en "In-Memory Data Source." Til produktion kan du bruge "HTTP Server Data Source."

Den "generelle interface" i den forrige JSFiddle er metoden "find posts title". Uanset hvordan du bygger interface, har du kontrol over alle opkaldere. Derfor er ændringer ligetil. Martin Fowler kalder det for en "ikke-offentliggjort grænseflade."

På den anden side, hvis serveren bryder kontrakten med deres Publicerede grænseflade, siger klasseattributten ændres fra posttitel til artikeltitel, skal du kun ændre implementering af datakilde. Du behøver ikke at foretage ændringer overalt.

Det, der er vigtigt at teste og have tidlige tilbagemeldinger, er om test mod adfærden, ikke dataene. Derfor er det vigtigt at designe koden for at reducere den nødvendige indsats for ændringer i logikken. I dette tilfælde er logikken omdannelsen af ​​input fra datakilden til HTML-uordnet liste.

Med det nye design har du afkoblet datakilden fra systemet under test. Derfor kan du fjerne Nock.

Det nye design reducerer også det arbejde, der er nødvendigt for at tilføje en ny regel til systemet uden at kopiere / indsætte:

Stadig har "HTTP-serverdatakilde" en vis ikke-testet logik i den private funktion "forespørgsel om titler fra html."

For at teste det kan du gentage det samme mønster. Tryk på bivirkningerne, og gør mekanismen "få anmodning" tilsluttet "HTTP-serverdatakilde." På denne måde kan du stadig teste koden uden Nock:

I betragtning af at du allerede har test for at bekræfte "listen over indlægstittel" fungerer med en "In-Memory Data Source", kan du beslutte at teste datakilden isoleret for at sikre, at den returnerer det rigtige resultat:

Du har skubbet bivirkningen helt ud af logikken. I dette tilfælde er den rigtige funktion "få anmodning" bivirkningen. Nu kan du bruge Nock til at dække det.

I betragtning af at logikken inde i "få anmodning" er triviel og Nock har en betydelig omkostning, giver det mening at have et lille antal integrationstests, der kan udøve hele applikationen, inklusive bivirkningen. Du kan bruge Nock til at undgå forbindelsen til en live server, og stadig bruge HTTP-anmodninger til at kontrollere, om applikationen giver et rimeligt svar, når alle brikkerne passer sammen.

Nock er nyttigt til at stoppe forbindelsen i HTTP-laget og til at give en statisk respons. Brug det imidlertid sparsomt. For hver test, du stubber, øger du betydelig kobling og omkostninger til ændring.

Hvis det ikke bruges sparsomt, kan Nock oprette et Nock Hell.

Problemet, du vil løse, er at reducere antallet af fejl og omkostningerne ved ændring. Hvis du ændrer strukturen i koden uden ændringer i opførslen, bør testene ikke gå i stykker. Hvis de gør det, har du undladt at skrive nyttige test.

Dit mål skal være at forbedre kvaliteten af ​​testdækning til den logik, du er interesseret i og opnå tidlig feedback. Alt dette uden at påvirke din evne til at refaktorere koden.

Isoler bivirkninger, og begræns brugen af ​​værktøjer som Nock til applikationens grænser.

Det skal give dig nok selvtillid til at foretage ændringer og ikke ødelægge ting.

Deltag i kampen, skub bivirkningerne, og derefter ... Lås det ud.

Tak for at have læst. Hvis du har nogle feedback, skal du kontakte mig på Twitter, Facebook eller Github.

Tak til Eduardo Slompo og Guilherme J. Tramontina for deres indsigtsfulde feedback til dette indlæg.