Integrarea testelor Cypress cu Docker, Buildkite și CICD #frontend@twiliosendgrid

Publicat: 2020-12-30

Am scris o mulțime de teste Cypress end-to-end (E2E) pentru a valida aplicațiile noastre web încă funcționează conform așteptărilor cu backend-ul. După ce am scris aceste teste de automatizare a browserului, ne-am dori să rulăm întotdeauna aceste teste Cypress sau să fie declanșate într-un fel ca testele noastre unitare înainte de a îmbina codul și de a le implementa în anumite medii. Acest lucru ne-a condus pe calea de a dori să rulăm testele noastre Cypress într-un container Docker pentru a ne integra cu furnizorul nostru de integrare continuă (CI) și cu mașinile pe care le folosim în cloud pentru a rula aceste containere.

Când vine vorba de fluxuri de implementare, folosim Buildkite ca furnizor de CI. Acest lucru ne permite să generăm o construcție de pași automati pentru aplicația noastră într-o conductă Buildkite atunci când intenționăm să mutăm codul peste tot. Pentru mai mult context, o conductă este un loc, de obicei legat de depozitul unei aplicații, unde putem analiza versiuni sau declanșa versiuni cu anumiți pași pentru a rula atunci când creați solicitări de extragere, împingeți modificări de cod noi, îmbina codul la master și implementați în diferite medii. . Creăm mai multe conducte în scopuri separate, cum ar fi pentru implementare, teste Cypress declanșate și teste specifice Cypress care rulează într-un program.

Această postare de blog presupune că ați scris deja teste Cypress înainte și că aveți unele teste în rulare, dar doriți idei despre cum să rulați aceste teste tot timpul în fluxurile dvs. de dezvoltare și implementare. Dacă doriți mai multă o privire de ansamblu despre scrierea testelor Cypress, puteți consulta această postare anterioară pe blog și apoi să o revedeți când aveți ceva de rulat.

Ne propunem să vă prezentăm idei despre cum puteți integra testele Cypress într-un container Docker cu furnizorul dvs. de CI, analizând cum am realizat-o cu Docker Compose și Buildkite în pipeline noastre de implementare. Aceste idei pot fi extinse în infrastructura dumneavoastră pentru strategiile, comenzile și variabilele de mediu pe care să le aplicați la declanșarea testelor Cypress.

Fluxul nostru standard CICD

În fluxul nostru standard de dezvoltare și implementare, am configurat două conducte:

  1. Primul se ocupă de pașii noștri de implementare pentru când împingem codul.
  2. Al doilea declanșează testele noastre Cypress să ruleze în paralel și să fie înregistrate. Succesul sau eșecul acestui lucru afectează conducta de implementare.

În conducta noastră de implementare, construim activele aplicației noastre web, rulăm teste unitare și avem pași pentru a declanșa testele Cypress selectate înainte de implementarea în fiecare mediu. Ne asigurăm că trec înainte de a debloca capacitatea de a face un buton de implementare. Aceste teste Cypress declanșate în a doua conductă rulează, de asemenea, într-un container Docker și sunt conectate la Tabloul de bord Cypress plătit printr-o cheie de înregistrare, astfel încât să putem privi în urmă videoclipurile, capturile de ecran și ieșirea din consolă din acele teste Cypress pentru a depana orice problemă.

Folosind intrările selectate ale Buildkite , am conceput o dinamică, alegeți-vă propria aventură, astfel încât utilizatorii să poată selecta „Da” sau „Nu” pentru a decide ce foldere cu specificații Cypress să ruleze și să verifice pe măsură ce introducem mai mult cod. Răspunsul implicit ar fi „Nu” pentru toate opțiunile, dar valoarea „Da” ar fi calea globală către folderul Cypress spec.

Uneori, nu dorim să rulăm toate testele Cypress dacă modificarea codului nostru nu afectează alte pagini. Noi, în schimb, vrem doar să declanșăm testele despre care știm că vor fi afectate. De asemenea, ar putea fi nevoie să implementăm o remediere rapidă în producție pentru o problemă urgentă de eroare, deoarece ne simțim suficient de încrezători pentru a nu rula testele noastre Cypress, care pot dura de la 0 la 10 minute, în funcție de câte teste declanșăm. Oferim un exemplu atât vizual, cât și în pașii YML pentru această parte.

Apoi, am implementat propriul nostru script Bash numit runCypress.sh pentru a rula după acel pas de selectare pentru a analiza valorile selectate „Da” sau „Nu”. Facem acest lucru pentru a forma o listă de căi de specificații separate prin virgulă pentru a rula și a adăuga ca opțiune, --spec , la eventuala noastră comandă Cypress care rulează într-un container Docker într-o conductă declanșată. Exportăm variabile de mediu, cum ar fi lista formată de specificații în „CYPRESS_SPECS” și mediul de testare actual în „CYPRESS_TEST_ENV” pentru a fi utilizate în conducta pe care o declanșăm la sfârșitul scriptului cu buildkite-agent pipeline upload "$DIRNAME"/triggerCypress.yml .

Poate ați observat cum exportăm și o variabilă de mediu „ASYNC”. În Buildkite, puteți alege ca un pas de construcție declanșat să fie blocant sau neblocant în ceea ce privește succesul sau eșecul. Dacă avem „ASYNC” setat la adevărat, pașii noștri principali de implementare vor continua să ruleze și nu vor aștepta ca testele Cypress declanșate într-o altă conductă să se termine. Succesul sau eșecul conductei nu afectează succesul sau eșecul conductei de implementare.

Dacă avem „ASYNC” setat la fals, pașii noștri principali ai conductei de implementare vor fi blocați până când se termină testele Cypress declanșate într-o conductă diferită. Succesul sau eșecul build-ului declanșat duce la succesul sau eșecul general al conductei de implementare, de unde începe după.

Când codul nostru este încă într-o ramură de caracteristici cu o cerere de extragere deschisă, ne place să facem mai multe modificări, să declanșăm câteva teste Cypress și să vedem cum se comportă lucrurile. Însă, nu vrem întotdeauna să blocăm rularea celorlalți pași ai conductei de implementare dacă testele declanșate eșuează, deoarece există potențial mai multe modificări pe parcurs. În acest scenariu, setăm „ASYNC” la false pentru a nu bloca dacă testele Cypress eșuează. Pentru cazul în care am îmbinat deja cererea de extragere în master și am implementat în staging, dar dorim să declanșăm teste Cypress înainte de a le implementa în producție, am setat „ASYNC” la adevărat, deoarece dorim ca testele Cypress să treacă întotdeauna înainte de a ieși în producție. .

Revenind la runCypress.sh , ne reamintim că scriptul declanșează rularea a doua conductă prin apelarea fișierului triggerCypress.yml cu valorile variabilelor de mediu atribuite. Fișierul triggerCypress.yml arată cam așa. Veți observa că pasul „declanșator” și interpolarea valorilor în mesajele de compilare sunt utile pentru depanare și nume de pași dinamici.

Indiferent dacă declanșăm testele Cypress să ruleze de la conducta noastră de implementare la o conductă de declanșare separată sau rulăm testele Cypress într-un program într-o conductă dedicată, urmăm și reutilizam aceiași pași în timp ce modificăm doar valorile variabilei de mediu.

Acești pași implică:

  1. Crearea imaginii Docker cu o etichetă cea mai recentă și o etichetă unică de versiune
  2. Împingeți imaginea Docker în registrul nostru privat
  3. Trag în jos aceeași imagine pentru a rula testele noastre Cypress pe baza valorilor variabilelor noastre de mediu într-un container Docker

Acești pași sunt subliniați într-un fișier pipeline.cypress.yml astfel:

Când declanșăm testele Cypress, va declanșa o construcție separată în conducta de declanșare Cypress. Pe baza succesului sau eșecului build-ului, testul Cypress fie va bloca, fie ne va permite să ne implementăm în producție atunci când trecem de la punere în scenă la producție pentru versiunile principale ale ramurilor.

Făcând clic pe pasul „Chiparos declanșat/integrare/…” vă va duce la construcția conductei declanșate cu o vedere ca aceasta pentru a vedea cum au decurs testele.

Dacă sunteți curios despre modul în care partea Docker este conectată, Dockerfile.cypress și package.json docker-compose.cypress.yml folosesc acele variabile de mediu exportate din conductele noastre pentru a utiliza apoi comanda Cypress corespunzătoare din pachetul.json al aplicației noastre, care indică spre dreapta. mediul de testare și rularea fișierelor de specificații selectate. Fragmentele de mai jos arată abordarea noastră generală pe care o puteți extinde și îmbunătăți pentru a fi mai flexibil.


În afara testelor efectuate în timpul ciclurilor noastre obișnuite de integrare și implementare, am creat conducte dedicate Buildkite. Aceste conducte rulează conform unui program pentru teste importante în mediul nostru de pregătire pentru a ne asigura că serviciile noastre de front-end și backend funcționează corect. Am refolosit pași similari în conductă, am ajustat anumite valori ale variabilelor de mediu în setările conductei Buildkite și am configurat un program cron pentru a rula la o oră programată. Acest lucru ne ajută să depistam multe erori și probleme cu mediul de pregătire, în timp ce continuăm să monitorizăm cât de bine funcționează testele noastre și dacă ceva în aval sau din propriul nostru cod poate fi dus la teste eșuate.

Paralelizarea

De asemenea, folosim indicatorul de paralelizare pentru a profita de numărul de mașini AWS pe care le putem porni din coada noastră de agenți de construcție configurată de echipa noastră de operațiuni. Cu acest steag de paralelizare, Cypress afișează automat un anumit număr de mașini pe baza numărului pe care l-am stabilit în proprietatea „paralelism” a Buildkite.

Am reușit să rulăm peste 200 de teste în aproximativ 5 minute pentru unul dintre depozitele noastre de aplicații.

Apoi împrăștie toate testele Cypress pentru a rula în paralel pe acele mașini, menținând în același timp înregistrarea fiecărui test pentru o anumită execuție de construcție. Acest lucru a mărit dramatic timpul nostru de testare!

Iată câteva sfaturi atunci când vă paralelizați testele Cypress:

  • Urmați sugestiile din Serviciul Dashboard pentru numărul optim de mașini și setați numărul de mașini într-o variabilă de mediu pentru flexibilitate în conductele dvs.
  • Împărțiți în fișiere de testare mai mici, mai ales împărțind testele de lungă durată în bucăți pe care le putem paraleliza mai bine pe mașini.
  • Asigurați-vă că testele dumneavoastră Cypress sunt izolate și nu se afectează unul pe celălalt sau depind unul de celălalt. Când aveți de-a face cu fluxuri legate de actualizare, creare sau ștergere, utilizați utilizatori și resurse de date separate pentru a evita ca testele să se lovească unul de celălalt și să se confrunte cu condiții de cursă. Fișierele dvs. de testare pot rula în orice ordine, așa că asigurați-vă că nu este o problemă atunci când rulați toate testele.
  • Pentru Buildkite, nu uitați să treceți valoarea variabilei de mediu Buildkite build ID în opțiunea --ci-build-id în plus față de opțiunea parallel , astfel încât să știe cu ce build unică să se asocieze atunci când paralelizează testele pe mașini.

Pentru a revizui:

Pentru a vă conecta testele Cypress la furnizorul dumneavoastră de CI, cum ar fi Buildkite, va trebui să:

  1. Creați o imagine Docker cu codul aplicației dvs., folosind imaginea de bază Cypress și dependențele necesare pentru a rula testele într-un mediu Node pe anumite browsere.
  2. Împingeți imaginea Docker într-un registru cu anumite etichete
  3. Trageți aceeași imagine în jos într-un pas ulterior
  4. Rulați testele Cypress în modul fără cap și cu taste de înregistrare dacă utilizați Cypress Dashboard Service.
  5. Setați diferite valori ale variabilelor de mediu și conectați-le la comenzile pe care le executați pentru ca Cypress să declanșeze testele Cypress selectate împotriva unui anumit mediu de testare din acele containere Docker.

Acești pași generali pot fi reutilizați și aplicați testelor Cypress care rulează conform unui program și altor cazuri de utilizare, cum ar fi declanșarea testelor pentru a rula pe browserele selectate, pe lângă conductele de implementare. Cheia este să valorificați capacitățile furnizorului dvs. de CI și să configurați comenzile pentru a fi flexibile și configurabile pe baza valorilor variabilelor de mediu.

Configurați comenzile pentru a fi flexibile și configurabile pe baza valorilor variabilelor de mediu.

Odată ce testele rulează în Docker cu furnizorul dvs. de CI (și dacă plătiți pentru Serviciul Dashboard), puteți profita de paralelizarea testelor pe mai multe mașini. Este posibil să trebuiască să modificați testele și resursele existente, astfel încât acestea să nu fie dependente de altele, pentru a evita ca testele să se lovească unul de celălalt.

Am discutat, de asemenea, idei pe care le puteți încerca personal, cum ar fi crearea unei suite de teste pentru a valida API-ul backend sau declanșarea testelor pentru a rula pe un browser pe care îl alegeți. Există, de asemenea, mai multe modalități de a configura integrarea continuă aici în documentele Cypress .

Mai mult, este important să rulați aceste teste Cypress în timpul fluxurilor de implementare sau la intervale programate pentru a vă asigura că mediile dvs. de dezvoltare funcționează conform așteptărilor tot timpul. Au existat nenumărate ori în care testele noastre Cypress au depistat probleme legate de serviciile backend din aval care au fost oprite sau modificate într-un fel, manifestându-se în erori de aplicație frontend. Ne-au salvat în special de erori neașteptate în paginile noastre web, după ce am lansat noile modificări ale codului React.

Menținerea testelor de promovare și monitorizarea cu sârguință a testelor eșuate în mediile noastre de testare duc la mai puține bilete de asistență și la clienți mai fericiți în producție. Menținerea unei suită sănătoase și stabile de teste Cypress atunci când împingeți noi modificări de cod oferă o mai mare încredere că lucrurile funcționează bine și vă recomandăm ca dvs. și echipele dvs. să faceți același lucru cu testele Cypress.

Pentru mai multe resurse despre testele Cypress, consultați următoarele articole:

  • Ce să țineți cont atunci când scrieți teste E2E
  • Prezentare generală de 1.000 de picioare despre scrierea testelor de chiparoși
  • TypeScript Toate lucrurile din testele tale Cypress
  • Confruntarea cu fluxurile de e-mail în testele Cypress
  • Idei pentru configurarea, organizarea și consolidarea testelor dvs. de Cypress