Pipeline de testare 101 pentru testarea front-end

Publicat: 2022-03-10
Rezumat rapid ↬ Testarea automată vă poate oferi multă încredere în îmbinarea modificărilor, în special în refactorizarea extinsă sau lucrul cu colegii de echipă. Ca rezultat, s-ar putea să te fi gândit să incluzi testarea ca parte a rutinei tale de construire pentru a obține cea mai mare valoare din ea. Nu știi de unde să începi? Să implementăm împreună canalul de testare de la zero.

Imaginează-ți această situație: te apropii rapid de un termen limită și folosești fiecare minut liber pentru a-ți atinge obiectivul de a finaliza această refactorizare complexă, cu o mulțime de modificări în fișierele CSS. Lucrezi chiar și la ultimii pași în timpul călătoriei cu autobuzul. Cu toate acestea, testele locale par să eșueze de fiecare dată și nu le puteți face să funcționeze. Nivelul tău de stres crește .

Există într-adevăr o scenă similară într-un serial bine-cunoscut: este din cel de-al treilea sezon al serialului TV Netflix, „Cum să vinzi droguri online (rapid)”:

Ei bine, el folosește teste cel puțin, ați putea crede. De ce este încă în suferință, s-ar putea să vă întrebați? Mai este mult loc de îmbunătățire și de evitat o astfel de situație, chiar dacă scrieți teste. Cum credeți că vă monitorizați baza de cod și toate modificările de la început? Drept urmare, nu vei experimenta astfel de surprize urâte, nu? Nu este prea dificil să includeți astfel de rutine automate de testare: să creăm împreună această conductă de testare de la început până la sfârșit.

Să mergem!

Primele lucruri în primul rând: Termenii de bază

O rutină de construcție vă poate ajuta să aveți încredere în refactorizarea mai complexă, chiar și în proiectele dumneavoastră secundare mici. Cu toate acestea, asta nu înseamnă că trebuie să fii inginer DevOps. Este esențial să înveți câțiva termeni și strategii și pentru asta ești aici, nu? Din fericire, ești în locul potrivit! Să începem cu termenii fundamentali pe care îi veți întâlni în curând atunci când aveți de-a face cu o conductă de testare pentru proiectul dvs. front-end.

Dacă căutați pe Google drumul prin lumea testării în general, s-ar putea întâmpla să fi dat deja de termenii „CI/CD” ca unul dintre primii termeni. Este prescurtarea pentru „Integrare continuă, livrare continuă” și „Implementare continuă” și descrie exact asta: După cum probabil ați auzit deja, este o metodă de distribuție a software-ului folosită de echipele de dezvoltare pentru a implementa modificările codului mai frecvent și mai fiabil. CI/CD implică două abordări complementare, care se bazează în mare măsură pe automatizare.

  • Integrare continuă
    Este un termen pentru măsurile de automatizare pentru a implementa modificări de cod mici și regulate și a le îmbina într-un depozit partajat. Integrarea continuă include pașii de construire și testare a codului dvs.

CD este acronimul atât pentru „Livrare continuă”, cât și pentru „Implementare continuă”, care sunt ambele concepte similare între ele, dar uneori folosite în contexte diferite. Diferența dintre ambele constă în domeniul de aplicare al automatizării:

  • Livrare continuă
    Se referă la procesul codului dvs. care a fost deja testat înainte, de unde echipa de operațiuni le poate implementa acum într-un mediu de producție live. Acest ultim pas poate fi totuși manual.
  • Desfăşurare continuă
    Se concentrează pe aspectul „desfășurare”, după cum sugerează și numele. Este un termen pentru procesul de lansare complet automatizat al modificărilor dezvoltate de la dreptul de depozit la producție, unde clientul le poate folosi direct.

Aceste procese urmăresc să permită dezvoltatorilor și echipelor să aibă un produs, pe care l-ați putea lansa oricând dacă doresc: să aibă încrederea unei aplicații monitorizate, testate și implementate continuu.

Pentru a realiza o strategie CI/CD bine concepută, majoritatea oamenilor și organizațiilor folosesc procese numite „conducte”. „Pipeline” este un cuvânt pe care l-am folosit deja în acest ghid fără a-l explica. Dacă te gândești la astfel de conducte, nu este prea exagerat să te gândești la tuburile care servesc drept linii de lungă distanță pentru a transporta lucruri precum gazul. O conductă din zona DevOps funcționează destul de asemănător: „transportă” software pentru implementare.

O ilustrare a conductei sub forma unui tub cu trei secțiuni: construiți, testați, implementați
O conductă CI/CD „adevărată” include câțiva pași care trebuie executați pentru a implementa o nouă versiune de software și, ca rezultat, automatizează procesul de livrare a software-ului. (Previzualizare mare)

Stai, sună ca o mulțime de lucruri de învățat și de reținut, nu? Nu am vorbit despre testare? Aveți dreptate în ceea ce privește: acoperirea conceptului complet de pipeline CI/CD va oferi suficient conținut pentru mai multe articole și dorim să ne ocupăm de o conductă de testare pentru proiectele front-end mici. Sau îți lipsește doar aspectul de testare al conductelor tale, concentrându-te astfel doar pe procesele de integrare continuă. Deci, în special, ne vom concentra pe partea „Testare” a conductelor. Prin urmare, vom crea o conductă „mică” de testare în acest ghid.

Bine, deci „partea de testare” este punctul nostru principal. În acest context, ce teste cunoști deja și îți vin în minte la prima vedere? Dacă mă gândesc la testarea în acest fel, acestea sunt tipurile de testare la care mă gândesc spontan:

  • Testarea unitară este un fel de test în care părțile sau unitățile minore testabile ale unei aplicații, numite unități, sunt testate individual și independent pentru funcționarea corectă.
  • Testarea de integrare se concentrează pe interacțiunea dintre componente sau sisteme. Acest tip de testare înseamnă că verificăm interacțiunea unităților și modul în care lucrează împreună.
  • Testarea end-to-end , sau testarea E2E, înseamnă că interacțiunile reale ale utilizatorului sunt simulate de computer; în acest sens, testarea E2E ar trebui să includă cât mai multe zone funcționale și părți ale stivei de tehnologie utilizate în aplicație.
  • Testarea vizuală este procesul de verificare a rezultatelor vizibile a unei aplicații și de comparare cu rezultatele așteptate. Cu alte cuvinte, ajută la găsirea „bucăturilor vizuale” în aspectul unei pagini sau al unui ecran diferit de erorile pur funcționale.
  • Analiza statică nu este tocmai testare, dar cred că este esențial să o menționăm aici. Vă puteți imagina că funcționează ca o corecție de ortografie: vă depanează codul fără a rula programul și detectează probleme de stil de cod. Această măsură simplă poate preveni multe erori.

Pentru a fi încrezători în îmbinarea unei refactorizări masive în proiectul nostru unic, ar trebui să luăm în considerare utilizarea tuturor acestor tipuri de testare în conducta noastră de testare. Dar începutul duce rapid la frustrare: s-ar putea să vă simțiți pierdut evaluând aceste tipuri de testare. De unde ar trebui să încep? Câte teste de ce tipuri sunt rezonabile?

Mai multe după săritură! Continuați să citiți mai jos ↓

Strategie: Piramide și trofee

Trebuie să lucrăm la o strategie de testare înainte de a ne lansa în construirea conductei noastre. Căutând răspunsuri la toate acele întrebări înainte, ați putea găsi o posibilă soluție în unele metafore: în web și în comunitățile de testare în special, oamenii tind să folosească analogii pentru a vă oferi o idee despre câte teste ar trebui să utilizați de ce tip.

Prima metaforă cu care veți întâlni probabil este piramida de automatizare a testelor. Mike Cohn a venit cu acest concept în cartea sa „Succeeding with Agile”, dezvoltată în continuare ca „Practical Test Pyramid” de Martin Fowler. Arata cam asa:

O piramidă de testare
„Piramida de testare practică” de Martin Fowler (previzualizare mare)

După cum vedeți, este format din trei niveluri, care corespund celor trei niveluri de testare prezentate. Piramida are scopul de a clarifica combinația potrivită de teste diferite, pentru a vă ghida în timpul dezvoltării unei strategii de testare:

  1. Unitate
    Găsești aceste teste pe stratul de bază al piramidei deoarece sunt de execuție rapidă și simplu de întreținut. Acest lucru se datorează izolării lor și faptului că vizează cele mai mici unități. Vedeți acesta pentru un exemplu de test unitar tipic care testează un produs foarte mic.
  2. Integrare
    Acestea se află în mijlocul piramidei, deoarece sunt încă acceptabile când vine vorba de viteză în execuție, dar tot îți aduc încrederea de a fi mai aproape de utilizator decât pot fi testele unitare. Un exemplu de test de tip integrare este un test API, de asemenea testele componente pot fi considerate acest tip.
  3. Teste E2E (numite și teste UI )
    După cum am văzut, aceste teste simulează un utilizator autentic și interacțiunea acestuia. Aceste teste au nevoie de mai mult timp pentru a fi executate și, prin urmare, sunt mai costisitoare - fiind plasate în vârful piramidei. Dacă doriți să inspectați un exemplu tipic pentru un test E2E, mergeți la acesta.

Cu toate acestea, în ultimii ani, această metaforă s-a simțit depășită. Unul dintre defectele sale, în special, este crucial pentru mine: analizele statice sunt ocolite în această strategie. Utilizarea fixatoarelor în stil cod sau a altor soluții de listing nu este luată în considerare în această metaforă, fiind un defect uriaș, în opinia mea. Lint și alte instrumente de analiză statică sunt o parte integrantă a conductei în uz și nu ar trebui ignorate.

Deci, să scurtăm acest lucru: ar trebui să folosim o strategie mai actualizată. Dar lipsa instrumentelor de scame nu este singurul defect - există chiar și un punct mai important de luat în considerare. În schimb, ne-am putea schimba ușor atenția: următorul citat rezumă destul de bine:

„Scrieți teste. Nu prea multe. Mai ales integrare.”

— Guillermo Rauch

Să descompunem acest citat pentru a afla despre el:

  • Scrie teste
    Destul de explicit - ar trebui să scrieți întotdeauna teste. Testele sunt cruciale pentru a insufla încredere în aplicația dvs. – atât pentru utilizatori, cât și pentru dezvoltatori. Chiar și pentru tine!
  • Nu prea multe
    Scrierea la întâmplare a testelor nu te va duce nicăieri; piramida de testare este încă valabilă în declarația sa de a păstra testele cu prioritate.
  • Mai ales integrare
    Un atu al testelor mai „scumpitoare” pe care piramida le ignoră este că încrederea în teste crește pe măsură ce vă deplasați în sus în piramidă. Această creștere înseamnă că atât utilizatorul, cât și dumneavoastră în calitate de dezvoltator sunt cel mai probabil să aibă încredere în acele teste.

Aceasta înseamnă că ar trebui să alegem teste care sunt mai aproape de utilizator, prin design. Drept urmare, s-ar putea să plătiți mai mult, dar veți primi înapoi multă valoare. S-ar putea să vă întrebați de ce nu alegeți testul E2E? Deoarece ei imită utilizatorii, nu sunt ei cei mai apropiați de utilizator, pentru început? Acest lucru este adevărat, dar sunt încă mult mai lent de executat și necesită întreaga stivă de aplicații. Deci, această rentabilitate a investiției este realizată mai târziu decât cu testele de integrare: în consecință, testele de integrare oferă un echilibru corect între încredere, pe de o parte, și viteză și efort, pe de altă parte.

Dacă îl urmărești pe Kent C.Dodds, aceste argumente îți pot suna familiare, mai ales dacă citești în special acest articol scris de el. Aceste argumente nu sunt întâmplătoare: a venit cu o nouă strategie în munca sa. Sunt ferm de acord cu punctele sale și leagă cele mai importante aici și altele în secțiunea de resurse. Abordarea sugerată de el provine din piramida de testare, dar o ridică la un alt nivel, schimbându-și forma pentru a reflecta prioritatea mai mare a testelor de integrare. Se numește „Trofeul de testare”.

Un trofeu de testare
Am făcut o notă de schiță rapidă, care s-ar putea să nu fie precisă la scară, dar își va înțelege punctul. (Previzualizare mare)

Trofeul de testare este o metaforă care înfățișează granularitatea testelor într-un mod ușor diferit; ar trebui să vă distribuiți testele în următoarele tipuri de teste:

  • Analiza statică joacă un rol vital în această metaforă. În acest fel, veți detecta greșelile de tipar, erorile de tipare și alte erori pur și simplu rulând pașii de depanare menționați.
  • Testele unitare ar trebui să asigure că cea mai mică unitate a dvs. este testată în mod corespunzător, dar trofeul de testare nu le va sublinia în aceeași măsură ca piramida de testare.
  • Integrarea este obiectivul principal, deoarece echilibrează costurile și încrederea mai mare în cel mai bun mod.
  • Testele UI , inclusiv testele E2E și vizuale, sunt în vârful trofeului de testare, similar cu rolul lor în piramida de testare.

Am optat pentru această strategie de testare a trofeului în majoritatea proiectelor mele și voi continua să o fac în acest ghid. Cu toate acestea, trebuie să renunț aici: desigur, alegerea mea se bazează pe proiectele la care lucrez în viața mea de zi cu zi. Astfel, beneficiile și selecția unei strategii de testare potrivite depind întotdeauna de proiectul la care lucrați. Deci, nu te simți rău dacă nu se potrivește nevoilor tale, voi adăuga resurse la alte strategii în paragraful corespunzător.

Alertă de spoiler minor: într-un fel, va trebui să mă abat și de la acest concept puțin, așa cum veți vedea în curând. Cu toate acestea, cred că e în regulă, dar vom ajunge la asta în scurt timp. Ideea mea este să mă gândesc la prioritizarea și distribuția tipurilor de testare înainte de a planifica și implementa conductele.

Cum să construiți acele conducte online (rapid)

Protagonistul celui de-al treilea sezon al serialului Netflix „Cum să vindeți droguri online (rapid)” este prezentat folosind Cypress pentru testarea E2E, în timp ce se apropie de un termen limită, cu toate acestea, a fost într-adevăr doar testare locală. Nu se vedea niciun CI/CD, ceea ce i-a provocat un stres inutil. Ar trebui să evităm presiunea protagonistului dat în episoadele corespunzătoare cu teoria pe care am învățat-o. Cu toate acestea, cum putem aplica aceste învățăminte în realitate?

În primul rând, avem nevoie de o bază de cod ca bază de testare pentru început. În mod ideal, ar trebui să fie un proiect pe care mulți dintre noi, dezvoltatorii front-end, îl vom întâlni. Cazul său de utilizare ar trebui să fie unul frecvent, fiind potrivit pentru o abordare practică și permițându-ne să implementăm o conductă de testare de la zero. Care ar putea fi un astfel de proiect?

Sugestia mea pentru o conductă primară

Primul lucru care mi-a venit în minte a fost de la sine înțeles: site-ul meu, adică pagina mea de portofoliu, este potrivit pentru a fi considerat un exemplu de bază de cod pentru a fi testat de pipeline-ul nostru aspirant. Este publicat open-source pe Github, astfel încât să îl puteți vizualiza și folosi liber. Câteva cuvinte despre stiva tehnologică a site-ului: Practic, am construit acest site pe Vue.js (din păcate încă pe versiunea 2 când am scris acest articol) ca cadru JavaScript cu Nuxt.js ca cadru web suplimentar. Puteți găsi exemplul complet de implementare în depozitul său GitHub.

Cu baza noastră de cod exemplu selectată, ar trebui să începem să aplicăm învățările noastre. Având în vedere faptul că dorim să folosim trofeul de testare ca punct de plecare pentru strategia noastră de testare, am venit cu următorul concept:

Sugestia unui autor pentru o conductă principală
Observați că unul dintre parantezele de pe imaginea conductei mele are o culoare transparentă? Am colorat după scop; acesta este punctul de unde vine mica mea declinare a răspunderii înainte. (Previzualizare mare)

Deoarece avem de-a face cu o bază de cod relativ mică, voi îmbina părțile testelor de unitate și de integrare. Cu toate acestea, acesta este doar un mic motiv pentru a face asta. Alte motive și mai importante sunt următoarele:

  • Definiția unei unități este adesea „de discutat”: dacă cereți unui grup de dezvoltatori să definească o unitate, veți primi în mare parte răspunsuri diferite. Deoarece unii se referă la o funcție, clasă sau serviciu - unități minore - un alt dezvoltator va conta în componenta completă.
  • Pe lângă aceste lupte de definiție, trasarea unei linii între unitate și integrare poate fi dificilă, deoarece este foarte neclară. Această luptă este reală, mai ales pentru Frontend, deoarece deseori avem nevoie de DOM pentru a valida baza de testare cu succes.
  • De obicei, este posibil să folosiți aceleași instrumente și biblioteci pentru a scrie ambele teste de integrare. Deci, s-ar putea să putem economisi resurse prin fuzionarea lor.

Instrument de alegere: acțiuni GitHub

Deoarece știm ce vrem să imaginăm în interiorul unei conducte, următorul este alegerea platformei de integrare și livrare continuă (CI/CD). Atunci când aleg o astfel de platformă pentru proiectul nostru, mă gândesc la cei cu care am acumulat deja experiență:

  • GitLab, după rutina zilnică la locul meu de muncă,
  • Acțiuni GitHub în majoritatea proiectelor mele secundare.

Cu toate acestea, există multe alte platforme din care să alegeți. Aș sugera să bazați întotdeauna alegerea pe proiectele dvs. și pe cerințele lor specifice, luând în considerare tehnologiile și cadrele utilizate, astfel încât să nu apară probleme de compatibilitate. Amintiți-vă, folosim un proiect Vue 2 care a fost deja lansat pe GitHub, potrivindu-se întâmplător cu experiența mea anterioară. În plus, acțiunile GitHub menționate au nevoie doar de depozitul GitHub al proiectului tău ca punct de plecare; pentru a crea și rula un flux de lucru GitHub Actions special pentru acesta. În consecință, voi merge cu GitHub Actions pentru acest ghid.

Deci, acele acțiuni GitHub vă oferă o platformă pentru a rula fluxuri de lucru definite în mod specific, dacă au loc anumite evenimente. Aceste evenimente sunt activități speciale din depozitul nostru care declanșează fluxul de lucru, de exemplu, împingerea modificărilor într-o ramură. În acest ghid, acele evenimente sunt legate de CI/CD, dar astfel de fluxuri de lucru pot automatiza și alte fluxuri de lucru, cum ar fi adăugarea de etichete la solicitări de extragere. GitHub le poate executa pe mașini virtuale Windows, Linux și macOS.

Pentru a vizualiza un astfel de flux de lucru, ar arăta astfel:

O ilustrare a fluxului de lucru al GitHub Action
Fluxul de lucru al unei acțiuni Github este un proces configurabil, automat (deci procesul complet descris în culoarea verde). (Previzualizare mare)

În acest articol, voi folosi un flux de lucru pentru a imagina o conductă; aceasta înseamnă că un singur flux de lucru va conține toți pașii noștri de testare, de la analiza statică până la testele UI de toate tipurile. Această conductă, sau numită „flux de lucru” în paragrafele următoare, va consta dintr-unul sau chiar mai multe joburi, care sunt un set de pași executați pe același runner.

Acest flux de lucru este exact structura pe care am vrut să o schițez în desenul de mai sus. În ea, aruncăm o privire mai atentă la un astfel de alergător care conține mai multe locuri de muncă; Pașii unui loc de muncă în sine sunt alcătuiți din diferiți pași. Acești pași pot fi unul din două tipuri:

  1. Un pas poate rula un script simplu.
  2. Un pas poate rula o acțiune. O astfel de acțiune este o extensie reutilizabilă și este adesea o aplicație completă, personalizată.

Ținând cont de acest lucru, un flux de lucru real al unei acțiuni GitHub arată astfel:

Un flux de lucru al unei acțiuni GitHub cu câteva explicații din partea autorului
O primă privire asupra sintaxei — totul într-unul. (Previzualizare mare)

Scrierea primei noastre acțiuni GitHub

În cele din urmă, putem scrie prima noastră acțiune Github și să scriem niște cod! Vom începe cu fluxul nostru de lucru de bază și prima noastră schiță a locurilor de muncă pe care vrem să le descriem. Reamintindu-ne trofeul de testare, fiecare lucrare se va asemana cu un strat din trofeul de testare. Pașii vor fi lucrurile pe care trebuie să le facem pentru a automatiza acele straturi.

Prin urmare, creez directorul .github/workflows/ pentru a stoca mai întâi fluxurile noastre de lucru. Vom crea un nou fișier numit tests.yml pentru a conține fluxul nostru de lucru de testare în acest director. Pe lângă sintaxa standard a fluxului de lucru văzută în desenul de mai sus, voi proceda după cum urmează:

  1. Voi numi fluxul nostru de lucru Tests CI .
  2. Deoarece vreau să-mi execut fluxul de lucru la fiecare push către ramurile mele de la distanță și să ofer o opțiune manuală pentru a-mi porni conducta, îmi voi configura fluxul de lucru să ruleze pe push și workflow_dispatch .
  3. Nu în ultimul rând, așa cum se menționează în paragraful „Sugestia mea pentru o conductă de bază”, fluxul meu de lucru va conține trei locuri de muncă:
    • static-eslint pentru analiza statica;
    • unit-integration-jest pentru testarea unitară și de integrare fuzionată într-un singur loc de muncă;
    • ui-cypress ca etapă UI, inclusiv testul E2E de bază și testarea regresiei vizuale.
  4. O mașină virtuală bazată pe Linux ar trebui să execute toate lucrările, așa că voi merge cu ubuntu-latest .

Introduceți sintaxa corectă a unui fișier YAML , prima schiță a fluxului nostru de lucru ar putea arăta astfel:

 name: Tests CI on: [push, workflow_dispatch] # On push and manual jobs: static-eslint: runs-on: ubuntu-latest steps: # 1 steps unit-integration-jest: runs-on: ubuntu-latest steps: # 1 step ui-cypress: runs-on: ubuntu-latest steps: # 2 steps: e2e and visual

Dacă doriți să explorați detalii despre fluxurile de lucru în acțiunea GitHub, nu ezitați să accesați documentația sa oricând. Oricum, ești, fără îndoială, conștient de faptul că pașii încă lipsesc. Nu-ți face griji - și eu sunt conștient. Așadar, pentru a umple această schiță a fluxului de lucru cu viață, trebuie să definim acești pași și să decidem ce instrumente și cadre de testare să folosim pentru proiectul nostru de portofoliu mic. Toate paragrafele următoare vor descrie joburile respective și vor conține câțiva pași pentru a face posibilă automatizarea acestor teste.

Analiza Statica

După cum sugerează trofeul de testare, vom începe cu linters și alte corecții de tip cod în fluxul nostru de lucru. În acest context, puteți alege dintre multe instrumente, iar câteva exemple le includ pe acestea:

  • Eslint ca reparator de stil de cod Javascript.
  • Stylelint pentru repararea codului CSS.
  • Ne putem gândi să mergem și mai departe, de exemplu, pentru a analiza complexitatea codului, ați putea să vă uitați la instrumente precum scrutinizer.

Aceste instrumente au în comun faptul că evidențiază erori în tipare și convenții. Cu toate acestea, vă rugăm să rețineți că unele dintre aceste reguli sunt o chestiune de gust. Depinde de tine să decizi cât de strict vrei să le aplici. Pentru a numi un exemplu, dacă veți tolera o indentație de două sau patru file. Este mult mai important să vă concentrați pe necesitatea unui stil de cod consecvent și pe identificarea cauzelor mai critice ale erorilor, cum ar fi folosirea „==” vs. „===”.

Pentru proiectul nostru de portofoliu și acest ghid, vreau să încep să instalez Eslint, deoarece folosim mult Javascript. Îl voi instala cu următoarea comandă:

 npm install eslint --save-dev

Desigur, pot folosi și o comandă alternativă cu managerul de pachete Yarn dacă prefer să nu folosesc NPM. După instalare, trebuie să creez un fișier de configurare numit .eslintrc.json . Să folosim o configurație de bază pentru moment, deoarece acest articol nu vă va învăța cum să configurați Eslint în primul rând:

 { "extends": [ "eslint:recommended", ] }

Dacă doriți să aflați despre configurația Eslint în detaliu, accesați acest ghid. În continuare, dorim să facem primii pași pentru a automatiza execuția Eslint. Pentru început, vreau să setez comanda pentru a executa Eslint ca script NPM. Reușesc acest lucru folosind această comandă în fișierul nostru package.json din secțiunea de script :

 "scripts": { "lint": "eslint --ext .js .", },

Apoi pot executa acest script nou creat în fluxul nostru de lucru GitHub. Cu toate acestea, trebuie să ne asigurăm că proiectul nostru este disponibil înainte de a face asta. Prin urmare, folosim actions/checkout@v2 preconfigurate, care face exact asta: Verificarea proiectului nostru, astfel încât fluxul de lucru al acțiunii GitHub să îl poată accesa. Următorul pas ar fi instalarea tuturor dependențelor NPM de care avem nevoie pentru proiectul meu de portofoliu. După aceea, suntem în sfârșit gata să rulăm scriptul nostru eslint! Ultima noastră sarcină de a folosi scame arată acum:

 static-eslint: runs-on: ubuntu-latest steps: # Action to check out my codebase - uses: actions/checkout@v2 # install NPM dependencies - run: npm install # Run lint script - run: npm run lint

S-ar putea să vă întrebați acum: „Eșuează” această conductă atunci când npm run lint într-un test eșuat? Da, acest lucru funcționează din cutie. De îndată ce am terminat de scris fluxul de lucru, ne vom uita la capturile de ecran de pe Github.

Unitate și integrare

În continuare, vreau să creez jobul nostru care să conțină pașii de unitate și integrare. În ceea ce privește cadrul folosit în acest articol, aș dori să vă prezint framework-ul Jest pentru testarea frontend. Desigur, nu trebuie să utilizați Jest dacă nu doriți - există multe alternative din care să alegeți:

  • Cypress oferă, de asemenea, testarea componentelor pentru a fi potrivite pentru testele de integrare.
  • Iasomia este un alt cadru la care să aruncăm o privire.
  • Și mai sunt multe; Am vrut doar să numesc câteva.

Jest este oferit ca sursă deschisă de Facebook. Cadrul își atribuie atenția pe simplitate, fiind în același timp compatibil cu multe cadre și proiecte JavaScript, inclusiv Vue.js, React sau Angular. De asemenea, pot folosi jest în tandem cu TypeScript. Acest lucru face cadrul foarte interesant, mai ales pentru proiectul meu de portofoliu mic, deoarece este compatibil și potrivit.

Putem începe direct instalarea Jest din acest folder rădăcină al proiectului meu de portofoliu, introducând următoarea comandă:

 npm install --save-dev jest

După instalare, sunt deja capabil să încep să scriu teste. Cu toate acestea, acest articol se concentrează pe automatizarea acestor teste prin utilizarea acțiunilor Github. Așadar, pentru a afla cum să scrieți un test unitar sau de integrare, vă rugăm să consultați următorul ghid. Când configurați jobul în fluxul nostru de lucru, putem proceda în mod similar cu static-eslint . Așadar, primul pas este crearea din nou a unui mic script NPM pe care să-l folosim în munca noastră mai târziu:

 "scripts": { "test": "jest", },

După aceea, vom defini jobul numit unit-integration-jest similar cu ceea ce am făcut deja pentru linters-ul nostru înainte. Deci, fluxul de lucru va verifica proiectul nostru. În plus, vom folosi două mici diferențe față de primul nostru loc de muncă static-eslint :

  1. Vom folosi o acțiune ca pas pentru a instala Node.
  2. După aceea, vom folosi scriptul nostru npm nou creat pentru a rula testul nostru Jest.

În acest fel, slujba noastră unit-integration-jest va arăta astfel::

 unit-integration-jest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Set up node - name: Run jest uses: actions/setup-node@v1 with: node-version: '12' - run: npm install # Run jest script - run: npm test

Teste UI: E2E și teste vizuale

Nu în ultimul rând, vom scrie Job-ul nostru ui-cypress , care va conține atât testarea E2E, cât și testarea vizuală. Este inteligent să le combin pe cele două într-un singur loc de muncă, deoarece voi folosi cadrul Cypress pentru ambele. Desigur, puteți lua în considerare și alte cadre precum cele de mai jos, NightwatchJS și CodeceptJS.

Din nou, vom acoperi doar elementele de bază pentru a-l configura în fluxul nostru de lucru GitHub. Dacă doriți să învățați cum să scrieți teste Cypress în detaliu, v-am explicat cu un alt ghid al meu care abordează tocmai asta. Acest articol vă va ghida prin tot ceea ce avem nevoie pentru a defini pașii noștri de testare E2E. Bine, mai întâi vom instala Cypress, așa cum am făcut cu celelalte cadre, folosind următoarea comandă din folderul nostru rădăcină:

 npm install --save-dev cypress

De data aceasta, nu este nevoie să definim un script NPM. Cypress ne oferă deja propria sa acțiune GitHub de utilizat, cypress-io/github-action@v2 . Acolo, trebuie doar să configuram câteva lucruri pentru ca acesta să ruleze:

  • Trebuie să ne asigurăm că aplicația noastră este complet configurată și funcționează, deoarece un test E2E necesită stiva completă de aplicații disponibilă.
  • Trebuie să denumim browserul în care rulăm testul E2E.
  • Trebuie să așteptăm ca serverul web să funcționeze pe deplin, astfel încât computerul să se poată comporta ca un utilizator real.

Din fericire, acțiunea noastră Cypress ne ajută să stocăm toate acele configurații cu zona with . În acest fel, jobul nostru actual GitHub arată astfel:

 steps: - name: Checkout uses: actions/checkout@v2 # Install NPM dependencies, cache them correctly # and run all Cypress tests - name: Cypress Run uses: cypress-io/github-action@v2 with: browser: chrome headless: true # Setup: Nuxt-specific things build: npm run generate start: npm run start wait-on: 'http://localhost:3000'

Teste vizuale: împrumutați niște ochi testului dvs

Amintiți-vă prima noastră intenție de a scrie acest ghid: am refactorizarea mea semnificativă cu o mulțime de modificări în fișierele SCSS - vreau să adaug testarea ca parte a rutinei de construire pentru a mă asigura că nu a întrerupt nimic altceva. Având analize statice, teste unitare, de integrare și E2E, ar trebui să fim destul de încrezători, nu? Adevărat, dar mai pot face ceva pentru a-mi face conducta și mai rezistentă la gloanț și perfectă. Ai putea spune că devine crema. Mai ales atunci când se ocupă de refactorizarea CSS, un test E2E poate fi doar de ajutor limitat, deoarece face doar lucrul pe care l-ați spus să îl facă notându-l în test.

Din fericire, există o altă modalitate de a prinde erori în afară de comenzile scrise și, prin urmare, în afară de concept. Se numește testare vizuală: vă puteți imagina acest tip de testare ca un puzzle care identifică diferența. Din punct de vedere tehnic, testarea vizuală este o comparație cu capturi de ecran care va face capturi de ecran ale aplicației dvs. și o va compara cu status quo-ul, de exemplu, din ramura principală a proiectului dumneavoastră. În acest fel, nicio problemă accidentală de stil nu va trece neobservată - cel puțin în zonele în care utilizați testarea vizuală. Acest lucru poate transforma testarea vizuală într-un salvator pentru refactorizările CSS mari, cel puțin din experiența mea.

Există multe instrumente de testare vizuală din care să alegeți și merită să le aruncați o privire:

  • Percy.io, un instrument de la Browserstack pe care îl folosesc pentru acest ghid;
  • Visual Regression Tracker dacă preferați să nu utilizați o soluție SaaS și să utilizați în același timp o sursă complet deschisă;
  • Aplicații cu suport AI. Există un ghid interesant pe care să îl consultați în revista Smashing despre acest instrument;
  • Cromatică după Storybook.

Pentru acest ghid și, practic, pentru proiectul meu de portofoliu, a fost vital să reutilizam testele mele Cypress existente pentru testarea vizuală. După cum am menționat anterior, voi folosi Percy pentru acest exemplu datorită simplității sale de integrare. Deși este o soluție SaaS, există încă multe părți furnizate open-source și există un plan gratuit care ar trebui să fie suficient pentru multe proiecte open source sau alte proiecte secundare. Cu toate acestea, dacă vă simțiți mai confortabil să vă găzduiți pe deplin în timp ce utilizați și un instrument open-source, puteți încerca Visual Regression Tracker.

Acest ghid vă va oferi doar o scurtă prezentare generală a lui Percy, care altfel ar oferi conținut pentru un articol complet nou. Cu toate acestea, vă voi oferi informațiile pentru a începe. Dacă doriți să vă scufundați în detalii acum, vă recomand să vă uitați la documentația lui Percy. Așadar, cum putem să dăm ochi testelor noastre, ca să spunem așa? Să presupunem că am scris deja unul sau două teste Cypress până acum. Imaginați-vă să arate așa:

 it('should load home page (visual)', () => { cy.get('[data-cy=Polaroid]').should('be.visible'); cy.get('[data-cy=FeaturedPosts]').should('be.visible'); });

Sigur, dacă vrem să instalăm Percy ca soluție de testare vizuală, putem face asta cu un plugin de chiparos. Deci, așa cum am făcut de câteva ori astăzi, îl instalăm în folderul rădăcină folosind NPM:

 npm install --save-dev @percy/cli @percy/cypress

După aceea, trebuie doar să importați pachetul percy/cypress în fișierul index cypress/support/index.js :

 import '@percy/cypress';

Acest import vă va permite să utilizați comanda snapshot a lui Percy, care va lua un instantaneu din aplicația dvs. În acest context, un instantaneu înseamnă o colecție de capturi de ecran luate din diferite ferestre sau browsere pe care le puteți configura.

 it('should load home page (visual)', () => { cy.get('[data-cy=Polaroid]').should('be.visible'); cy.get('[data-cy=FeaturedPosts]').should('be.visible'); // Take a snapshot cy.percySnapshot('Home page'); });

Revenind la fișierul nostru de flux de lucru, vreau să definesc testarea Percy ca al doilea pas al jobului. În el, vom rula scriptul npx percy exec -- cypress run pentru a rula testul împreună cu Percy. Pentru a conecta testele și rezultatele noastre la proiectul nostru Percy, va trebui să trecem jetonul nostru Percy, ascuns de un secret GitHub.

 steps: # Before: Checkout, NPM, and E2E steps - name: Percy Test run: npx percy exec -- cypress run env: PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}

De ce am nevoie de un jeton Percy? Se datorează faptului că Percy este o soluție SaaS pentru menținerea capturilor de ecran. Acesta va păstra capturile de ecran și status quo-ul pentru comparație și ne va oferi un flux de lucru de aprobare a capturilor de ecran. Acolo, puteți aproba sau respinge orice modificare viitoare:

Fluxul de lucru de aprobare al lui Percy
(Previzualizare mare)

Vizualizarea lucrărilor noastre: integrarea GitHub

Felicitări! Am construit cu succes primul nostru flux de lucru GitHub. Să aruncăm o privire finală asupra fișierului nostru complet al fluxului de lucru din depozitul paginii mele de portofoliu. Nu vă întrebați cum arată în utilizare practică? Puteți găsi acțiunile GitHub de lucru în fila „Acțiuni” a depozitului dvs.:

Fila Acțiuni GitHub
(Previzualizare mare)

Acolo, puteți găsi toate fluxurile de lucru, care sunt echivalente cu fișierele fluxului de lucru. Dacă aruncați o privire asupra unui flux de lucru, de exemplu, fluxul meu de lucru „Tests CI”, puteți inspecta toate lucrările acestuia:

Testează vizualizarea fluxului de lucru CI
(Previzualizare mare)

Dacă doriți să aruncați o privire la unul dintre joburile dvs., îl puteți selecta și în bara laterală. Acolo, puteți inspecta jurnalul joburilor dvs.:

Lucru eșuat cu erori
(Previzualizare mare)

Vedeți, puteți detecta erori dacă se întâmplă în interiorul conductei dvs. Apropo, fila „acțiune” nu este singurul loc în care poți verifica rezultatele acțiunilor tale GitHub. Le puteți inspecta și în solicitările dvs. de extragere:

Solicitările de extragere ale acțiunilor GitHUb
(Previzualizare mare)

I like to configure those GitHub actions the way they need to be executed successfully: Otherwise, it's not possible to merge any pull requests into my repository.

Concluzie

CI/CD helps us perform even major refactorings — and dramatically minimizes the risk of running into nasty surprises. The testing part of CI/CD is taking care of our codebase being continuously tested and monitored. Consequently, we will notice errors very early, ideally before anyone merges them into your main branch. Plus, we will not get into the predicament of correcting our local tests on the way to work — or even worse — actual errors in our application. I think that's a great perspective, right?

To include this testing build routine, you don't need to be a full DevOps engineer: With the help of some testing frameworks and GitHub actions, you're able to implement these for your side projects as well. I hope I could give you a short kick-off and got you on the right track.

I'm looking forward to seeing more testing pipelines and GitHub action workflows out there! ️

Resurse

  • An excellent guide on CI/CD by GitHub
  • “The practical test pyramid”, Ham Vocke
  • Articles on the testing trophy worth reading, by Kent C.Dodds:
    • “Write tests. Not too many. Mostly integration”
    • “The Testing Trophy and Testing Classifications”
    • “Static vs Unit vs Integration vs E2E Testing for Frontend Apps”
  • I referred to some examples of the Cypress real world app
  • Documentation of used tools and frameworks:
    • GitHub actions
    • Eslint docs
    • Gest documentație
    • Documentație Cypress
    • Percy documentation