Dezvoltatorii sunt de obicei preocupați de calitatea codului lor. Există diferite tipuri de teste care ne ajută să evităm încălcarea codului atunci când se adaugă o nouă funcție într-un proiect. Dar ce putem face pentru a ne asigura că componentele nu arată diferit în timp?

În această postare, veți învăța cum să utilizați Cypress pentru a captura părți ale paginilor unui site web. După aceea, veți integra instrumentul de testare în CI pentru a vă asigura că în viitor nimeni nu va face modificări nedorite proiectului dumneavoastră.

Motivația mea pentru crearea acestei strategii de testare a venit de la muncă. La Thinkific avem un sistem de proiectare intern și am adăugat Cypress pentru a evita surprize atunci când lucrăm în fișiere CSS / JS.

Până la sfârșitul acestui post vom avea PR-uri cu teste Cypress:

Cypress bot

ad-banner

Înainte de a începe

Am creat un eșantion de site web pentru a imita o bibliotecă de componente. Este un site web foarte simplu creat cu TailwindCSS și găzduit în Vercel. Documentează 2 componente: insignă și buton.

Puteți verifica cod sursa în GitHub. Site-ul este static și se află în interiorul public pliant. Puteți vedea site-ul local executând npm run serve și verificarea în browser http: // localhost: 8000.

Exemplu de site web

Adăugarea Cypress și a instantaneului Cypress Image

Începeți prin clonarea fișierului exemplu depozit. Apoi, creați o ramură nouă și instalați Instantaneu Cypress Image, pachetul responsabil de captarea / compararea capturilor de ecran.

git checkout -b add-cypress
npm install -D cypress cypress-image-snapshot

După adăugarea pachetelor, sunt necesari câțiva pași suplimentari pentru a adăuga Cypress Image Snapshot în Cypress.

Creeaza o cypress/plugins/index.js fișier cu următorul conținut:

const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');

module.exports = (on, config) => {
  addMatchImageSnapshotPlugin(on, config);
};

Apoi, creați un cypress/support/index.js fișier care conține:

import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command';

addMatchImageSnapshotCommand();

Crearea testului de captură de ecran

Este timpul să creați testul de captură de ecran. Iată planul:

  1. Cypress va vizita fiecare pagină (insignă și buton) a proiectului.
  2. Cypress va face o captură de ecran a fiecărui exemplu din pagină. Pagina insignă are 2 exemple (Implicit și Pilula), în timp ce Pagina Buton are 3 exemple (implicit, pastilă și contur). Toate aceste exemple se află în interiorul unui <div> element cu a cypress-wrapper. Această clasă a fost adăugată cu singura intenție de a identifica ceea ce trebuie testat.

Primul pas este crearea fișierului de configurare Cypress (cypress.json):

{
  "baseUrl": "http://localhost:8000/",
  "video": false
}

baseUrl este site-ul web care rulează local. După cum am menționat mai devreme, npm run serve va servi conținutul public pliant. A doua opțiune, video dezactivează înregistrarea video Cypress, pe care nu o vom folosi în acest proiect.

Este timpul să creați testul. În cypress/integration/screenshot.spec.js, adăuga:

const routes = ['badge.html', 'button.html'];

describe('Component screenshot', () => {
  routes.forEach((route) => {
    const componentName = route.replace('.html', '');
    const testName = `${componentName} should match previous screenshot`;

    it(testName, () => {
      cy.visit(route);
  
      cy.get('.cypress-wrapper').each((element, index) => {
        const name = `${componentName}-${index}`;
  
        cy.wrap(element).matchImageSnapshot(name);
      });
    });
  });
});

În codul de mai sus, creez dinamic teste bazate pe routes matrice. Testul va crea o imagine pe fiecare .cypress-wrapper element pe care îl are pagina.

Ultimul, în interiorul package.json să creăm comanda pentru a declanșa testele:

{
  "test": "cypress"
}  

De aici, există 2 opțiuni: rulați Cypress în modul fără cap cu npm run cypress run sau folosiți Cypress Test Runner cu npm run cypress open.

Opțiune fără cap

Folosind npm run cypress run, ieșirea ar trebui să fie similară cu următoarea imagine:

Rezultatul primului test

Testele vor trece și vor fi create 5 imagini sub /snapshots/screenshot.spec.js pliant.

Opțiunea Test Runner

Folosind npm run cypress open, Cypress Test Runner va fi deschis și puteți urmări testele pas cu pas.

Captură de ecran Cypress Test Runner

Prima noastră etapă este realizată, așa că hai să fuzionăm această ramură pentru a stăpâni. Dacă doriți să vedeți munca făcută până acum, săriți în a mea Trageți cererea.

Folosind Cypress în Docker

Dacă rulați testul de mai sus alternând între fără cap și Test Runner, este posibil să observați că captura de ecran va varia.

Folosind Test Runner cu un computer cu afișaj retină, puteți obține imagini retină (2x), în timp ce modul fără cap nu vă oferă capturi de ecran de înaltă calitate.

De asemenea, este important să spuneți că capturile de ecran pot varia în funcție de sistemul dvs. de operare.

Linux și Windows, de exemplu, au aplicații cu bare de derulare vizibile, în timp ce macOS ascunde bara de derulare.

Dacă conținutul capturat în captura de ecran nu se potrivește cu o componentă, este posibil să aveți sau nu o bară de derulare. Dacă proiectul dvs. se bazează pe fonturile implicite ale sistemului de operare, capturile de ecran vor fi, de asemenea, diferite în funcție de mediu.

Pentru a evita aceste neconcordanțe, testele vor rula în interiorul Docker, astfel încât computerul dezvoltatorului să nu afecteze capturile de ecran.

Să începem prin a crea o nouă ramură:

git checkout -b add-docker

Cypress oferă diferite imagini Docker – puteți consulta detaliile în documentația lor și blogul lor.

Pentru acest exemplu, voi folosi cypress/included imagine, care include Electron și este gata de utilizare.

Trebuie să facem două modificări: schimbăm baseUrl în cypress.json fişier:

{
  "baseUrl": "http://host.docker.internal:8000/",
}

si test comandă în package.json fişier:

{
  "test": "docker run -it -e CYPRESS_updateSnapshots=$CYPRESS_updateSnapshots --ipc=host -v $PWD:/e2e -w /e2e cypress/included:4.11.0"
}

Alergare npm run test ne va aduce o problemă:

Rezultatul testului

Imaginile sunt ușor diferite, dar de ce? Să vedem ce este în interiorul __diff_output__ pliant:

Diferența lui Button

După cum am menționat mai devreme, inconsecvențele tipografiei! Componenta Button utilizează fontul implicit al sistemului de operare. Deoarece Docker rulează în Linux, fontul redat nu va fi același pe care l-am instalat pe macOS.

De când ne-am mutat la Docker, aceste capturi de ecran sunt învechite. Este timpul să actualizați instantaneele:

CYPRESS_updateSnapshots=true npm run test

Vă rugăm să rețineți că prefixez comanda test cu variabila de mediu CYPRESS_updateSnapshots.

A doua etapă este realizată. În cazul în care aveți nevoie de ajutor, consultați cerere de tragere.

Să fuzionăm această ramură și să mergem înainte.

Adăugarea CI

Următorul nostru pas este adăugarea testelor în CI. Există diferite soluții CI pe piață, dar pentru acest tutorial, voi folosi Semaphore. Nu sunt afiliat cu ei și le folosesc produsul la locul de muncă, așa că a fost pentru mine o alegere firească.

Configurația este simplă și poate fi adaptată la alte soluții precum CircleCI sau Github Actions.

Înainte de a crea fișierul de configurare Semaphore, să pregătim proiectul pentru a rula în CI.

Primul pas este instalarea start-server-and-test. După cum spune numele pachetului, va porni un server, va aștepta adresa URL și apoi va rula o comandă de testare:

npm install -D start-server-and-test

În al doilea rând, editați fișierul package.json fişier:

{
  "test": "docker run -it -e CYPRESS_baseUrl=$CYPRESS_baseUrl -e CYPRESS_updateSnapshots=$CYPRESS_updateSnapshots --ipc=host -v $PWD:/e2e -w /e2e cypress/included:4.11.0",
  "test:ci": "start-server-and-test serve http://localhost:8000 test"
}

În test script, adăugăm CYPRESS_baseUrl variabilă de mediu. Acest lucru ne va permite să schimbăm dinamic adresa URL de bază utilizată de Cypress. De asemenea, adăugăm test:ci script, care va rula pachetul pe care tocmai l-am instalat.

Suntem pregătiți pentru semafor. Creați .semaphore/semaphore.yml fișier cu următorul conținut:

 1 version: v1.0
 2 name: Cypress example
 3 agent:
 4   machine:
 5     type: e1-standard-2
 6     os_image: ubuntu1804
 7 blocks:
 8   - name: Build Dependencies
 9     dependencies: []
10     task:
11       jobs:
12         - name: NPM
13           commands:
14             - sem-version node 12
15             - checkout
16             - npm install
17   - name: Tests
18     dependencies: ['Build Dependencies']
19     task:
20       prologue:
21         commands:
22           - sem-version node 12
23           - checkout
24       jobs:
25         - name: Cypress
26           commands:
27             - export CYPRESS_baseUrl="http://$(ip route | grep -E '(default|docker0)' | grep -Eo '([0-9]+.){3}[0-9]+' | tail -1):8000"
28             - npm run test:ci

Defalcarea configurației în detaliu:

  • Liniile 1-6 definesc ce tip de instanță vom folosi în mediul lor
  • Liniile 8 și 16 creează 2 blocuri: primul bloc, „Construiți dependențe” va rula npm install, descărcarea dependențelor de care avem nevoie. Al doilea bloc, „Teste”, va rula Cypress, cu câteva diferențe.
  • În linia 27, setăm dinamic CYPRESS_baseUrl variabilă de mediu bazată pe IP Docker este utilizată în acest moment. Aceasta va înlocui http://host.docker.internal:8000/, care poate să nu funcționeze în toate mediile.
  • În linia 28, vom rula în cele din urmă testul folosind start-server-and-test: odată ce serverul este pregătit pentru conexiuni, Cypress va rula suita de testare.

Se face încă o etapă importantă, timpul de fuziune a filialei noastre! Puteți verifica Solicitare pull care conține toate fișierele din această secțiune și verificați construiți în interiorul semaforului.

Înregistrarea testelor în cypress.io

Citirea rezultatelor testelor în CI nu este foarte prietenoasă. În acest pas, vom integra proiectul nostru cu chiparos.io.

Următorii pași se bazează pe Documentația Cypress.

Să începem prin a obține un ID de proiect și o cheie de înregistrare. În terminal, creați o ramură nouă și rulați:

git checkout -b add-cypress-recording
CYPRESS_baseUrl=http://localhost:8000 ./node_modules/.bin/cypress open

Anterior am menționat că vom folosi Cypress în Docker. Dar aici deschidem Cypress la nivel local, deoarece aceasta este singura modalitate de integrare cu tabloul de bord al site-ului web.

În Cypress, să mergem la fila Rulează, să facem clic în „Configurare proiect pentru înregistrare” și să alegem un nume și vizibilitate. Vom primi un projectId care este adăugat automat în cypress.json fișier și o cheie de înregistrare privată. Iată un videoclip cu pașii:

În Semafor, am adăugat cheia de înregistrare ca o variabilă de mediu numită CYPRESS_recordKey. În continuare, să actualizăm scriptul de testare pentru a utiliza variabila:

{
  "test:ci": "start-server-and-test 'serve' 8000 'npm run test -- run --record --key $CYPRESS_recordKey'"
}

Este cam tot ceea ce trebuie făcut. În Solicitare pull putem vedea integrarea cypress.io în comentarii. Există chiar și un link profund care ne duce la tabloul de bord al acestora și afișează toate capturile de ecran. Vedeți videoclipul de mai jos:

E timpul să ne îmbinăm munca și acesta este sfârșitul integrării noastre.

Testarea în viața reală

Imaginați-vă că lucrăm la o schimbare care afectează umplerea butoanelor: timpul pentru a testa dacă Cypress va capta diferența.

În site-ul web de exemplu, să dublăm umplutura orizontală de la 16 px la 32 px. Această modificare este destul de simplă, deoarece utilizăm Tailwind CSS: px-4 este înlocuit de px-8. Iată asta Solicitare pull.

După cum ne-am putea aștepta, Cypress a constatat că butonul nu se potrivește cu capturile de ecran. Vizitând pagina, putem verifica captura de ecran a testului defect:

Fișierul diff arată captura de ecran originală în stânga, rezultatul curent în dreapta și sunt combinate în mijloc. De asemenea, avem opțiunea de a descărca imaginea, astfel încât să putem vedea mai bine problema:

Buton înainte și după

Dacă aceasta nu este o problemă, actualizați capturile de ecran:

CYPRESS_updateSnapshots=true npm run test

Sfarsit

Asta e pentru astăzi. Sper că ați aflat cum Cypress poate fi util pentru a vă asigura că nimeni nu adaugă modificări neașteptate unui proiect.

Postat și pe blogul meu. Dacă îți place acest conținut, urmărește-mă Stare de nervozitate și GitHub.