Pentru a testa un sistem, izolați efectele secundare

Eliminarea efectelor secundare este una dintre cele mai bune metode de a construi coduri testabile

Imaginea unui meci de box dintre doi luptători de sex masculin. Fețele lor sunt în afara cadrului. Luptătorul din stânga a trimis un cârlig stâng către luptătorul din dreapta. Luptătorul din dreapta poartă un pantaloni scurți roșii cu un mic simbol al Uniunii Sovietice.

Nock este o faimoasă bibliotecă scrisă în JavaScript, utilă pentru a stub cererile de rețea. Întoarce un răspuns static pentru teste, astfel încât acestea să poată rula chiar dacă un server HTTP nu este disponibil.

Totuși, este și un miros.

Cuplarea rezultată între Sursa de date și Sistemul testat este un cost care poate afecta refactorizarea și mentenanța codului.

Iata de ce.

Să zicem că există un server care returnează o listă de postări și o funcție care consumă răspunsul de la serverul respectiv pentru a crea o listă de titluri de postare. Testul pentru funcție folosește Nock pentru a stuba răspunsul de la server:

O diagramă care arată un bloc din stânga cu subtitrarea „creați lista postărilor”. O săgeată indică un bloc cu titlul „răspunsuri postări”. Cealaltă săgeată indică un bloc cu titlul „adună”. Blocul cu titlul „preluare” are o săgeată care indică direcția unui bloc cu titlul „server HTTP”. Ultima săgeată este întreruptă cu eticheta „Nocked”.

Codul are o acoperire decentă. Cu toate acestea, există unele probleme cu aceasta.

Dacă aduceți modificări tipului de conținut al răspunsului, trebuie să schimbați testele, chiar dacă comportamentul codului rămâne același:

Același lucru se aplică dacă efectuați modificări la adresa URL, anteturi sau parametri pe care Nock o stub. Trebuie să schimbați testele chiar dacă comportamentul sistemului rămâne același:

Funcția „crea lista de postări” este Sistemul sub test (SUT). Datele de la apelul HTTP sunt Sursa de date.

Puteți proiecta codul astfel încât Sursa de date să aibă o interfață generală conectabilă la SUT. În acest caz, puteți exercita logica fără a fi nevoie de o configurație prea mare.

O diagramă care arată un bloc din stânga cu titlul „listă de titluri de postare.” O săgeată indică un bloc cu titlul „Sursă de date în memorie”. Cealaltă săgeată indică un bloc cu titlul „Date server HTTP. Sursă.

Pentru un mediu de testare, puteți injecta o „Sursă de date în memorie”. Pentru producție, puteți utiliza „Sursa de date a serverului HTTP”.

„Interfața generală” din JSFiddle precedentă este metoda „find title title”. Indiferent de modul în care construiți interfața, aveți controlul asupra tuturor apelanților. Prin urmare, schimbările sunt simple. Martin Fowler numește această „interfață nepublicată”.

Pe de altă parte, dacă serverul încalcă contractul interfeței lor publicate, spuneți că atributul clasei se schimbă de la post-title la articol-title, trebuie doar să modificați implementarea sursei de date. Nu trebuie să faceți schimbări peste tot.

Lucrul care este important pentru a testa și a avea feedback timpuriu este testarea împotriva comportamentului, nu datele. Prin urmare, este esențial să proiectăm codul pentru a reduce cantitatea de efort necesară pentru modificările aduse logicii. În acest caz, logica este transformarea intrării de la Sursa de date în lista HTML neordonată.

Cu noul design, ați decuplat Sursa de date de la sistemul supus testului. Prin urmare, puteți elimina Nock.

Noul proiect reduce, de asemenea, munca necesară pentru a adăuga o nouă regulă în sistem fără copiere / lipire:

Totuși, „Sursa de date a serverului HTTP” are o logică testată în cadrul funcției private, „interogare postează titlul de la html.”

Pentru a testa acest lucru, puteți repeta același model. Apăsați efectele secundare și faceți mecanismul „obține cerere” conectabil la „Sursa de date a serverului HTTP”. În acest fel, puteți testa totuși codul fără a fi nevoie de Nock:

Având în vedere că aveți deja teste pentru a confirma „lista titlurilor postărilor” funcționează cu o „Sursă de date în memorie”, puteți decide să testați Sursa de date în mod izolat pentru a vă asigura că returnează rezultatul corect:

Ați împins complet efectul secundar din logică. În acest caz, efectul secundar este efectul secundar. Acum puteți utiliza Nock pentru a acoperi asta.

Cu toate acestea, având în vedere că logica din „cererea de primire” este banală și Nock are un cost semnificativ, este logic să existe un număr mic de teste de integrare care să poată exercita întreaga aplicație, inclusiv efectul secundar. Puteți utiliza Nock pentru a evita conexiunea la un server live și, totuși, puteți utiliza cereri HTTP pentru a verifica dacă aplicația returnează un răspuns rezonabil atunci când toate piesele se potrivesc.

Nock este util pentru a stub conexiunea în stratul HTTP și pentru a oferi un răspuns static. Cu toate acestea, folosește-l puțin. Pentru fiecare test pe care îl încercați, creșteți cuplarea semnificativă și costul schimbării.

Dacă nu este folosit cu mod redus, Nock poate crea un Nock Hell.

Problema pe care doriți să o rezolvați este reducerea numărului de erori și a costurilor modificărilor. Dacă schimbați structura codului fără modificări ale comportamentului, testele nu ar trebui să se rupă. Dacă o fac, atunci nu ați reușit să scrieți teste utile.

Obiectivul tău ar trebui să fie îmbunătățirea calității acoperirii testelor în funcție de logica de care îți pasă și să obții feedback timpuriu. Toate acestea fără a vă afecta abilitatea de a refactoriza codul.

Izolați efectele secundare și restricționați utilizarea unor instrumente precum Nock la limitele aplicației.

Asta ar trebui să vă ofere suficientă încredere pentru a face schimbări și pentru a nu sparge lucrurile.

Alăturați-vă luptei, împingeți efectele secundare și apoi ... Bifați-l.

Mulțumesc pentru citit. Dacă aveți feedback, contactați-ne pe Twitter, Facebook sau Github.

Mulțumim lui Eduardo Slompo și Guilherme J. Tramontina pentru feedback-ul lor interesant pentru această postare.