Una guida completa a Cypress, il potente framework di testing end-to-end, che copre installazione, scrittura di test, debugging, integrazione CI/CD e best practice.
Cypress: La Guida Definitiva al Testing End-to-End per Applicazioni Web
Nel panorama dello sviluppo web in rapida evoluzione odierno, garantire la qualità e l'affidabilità delle applicazioni web è fondamentale. Il testing End-to-End (E2E) gioca un ruolo cruciale nel verificare che tutti i componenti di un'applicazione funzionino perfettamente insieme dalla prospettiva dell'utente. Cypress è emerso come un framework di testing E2E leader, offrendo un'esperienza intuitiva per gli sviluppatori, potenti funzionalità ed eccellenti prestazioni. Questa guida completa ti guiderà attraverso tutto ciò che devi sapere per iniziare con Cypress e testare efficacemente le tue applicazioni web.
Cos'è Cypress?
Cypress è uno strumento di testing front-end di nuova generazione costruito per il web moderno. A differenza dei framework di testing tradizionali che eseguono test in un browser, Cypress opera direttamente nel browser, offrendoti un controllo e una visibilità senza pari sul comportamento della tua applicazione. È progettato per essere veloce, affidabile e facile da usare, rendendolo una scelta popolare tra sviluppatori e ingegneri QA in tutto il mondo. Cypress è scritto in JavaScript e si esegue all'interno del browser, rendendolo molto performante e offrendo un accesso senza pari agli elementi interni dell'applicazione.
Vantaggi chiave dell'utilizzo di Cypress
- Intuitivo per gli sviluppatori: Cypress fornisce un'API pulita e intuitiva, rendendo facile la scrittura e il debug dei test.
- Time Travel: Cypress scatta snapshot dello stato della tua applicazione durante ogni comando di test, permettendoti di tornare indietro nel tempo e vedere esattamente cosa è successo in qualsiasi momento.
- Ricaricamenti in tempo reale: Cypress si ricarica automaticamente quando apporti modifiche ai tuoi test, fornendo un feedback immediato.
- Attesa automatica: Cypress attende automaticamente che gli elementi diventino visibili o interagibili prima di eseguire azioni, eliminando la necessità di attese esplicite.
- Controllo della rete: Cypress ti consente di simulare le richieste e le risposte di rete, consentendoti di simulare diversi scenari e testare la gestione degli errori della tua applicazione.
- Debuggabilità: Cypress fornisce eccellenti strumenti di debug, tra cui un potente debugger e messaggi di errore dettagliati.
- Test cross-browser: Cypress supporta più browser, tra cui Chrome, Firefox, Edge ed Electron.
- Test headless: Esegui test in modalità headless per un'esecuzione più rapida negli ambienti CI/CD.
- Asserzioni integrate: Cypress fornisce un ricco set di asserzioni integrate per verificare il comportamento previsto della tua applicazione.
Installazione e configurazione
Iniziare con Cypress è semplice. Ecco come installarlo:
- Prerequisiti: Assicurati di avere Node.js e npm (Node Package Manager) installati sul tuo sistema. Puoi scaricarli dal sito Web ufficiale di Node.js.
- Installa Cypress: Apri il tuo terminale o prompt dei comandi, vai alla directory del tuo progetto ed esegui il seguente comando:
- Apri Cypress: Una volta completata l'installazione, puoi aprire il Cypress Test Runner eseguendo:
npm install cypress --save-dev
npx cypress open
Questo comando avvierà il Cypress Test Runner, che fornisce un'interfaccia grafica per l'esecuzione e il debug dei tuoi test.
Scrivere il tuo primo test Cypress
Creiamo un semplice test per verificare che la homepage di un sito web venga caricata correttamente. Crea un nuovo file denominato `example.cy.js` nella directory `cypress/e2e` del tuo progetto.
// cypress/e2e/example.cy.js
describe('My First Test', () => {
it('Visits the Kitchen Sink', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
cy.url().should('include', '/commands/actions')
cy.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
})
})
Analizziamo questo test:
- `describe()`: Definisce una suite di test, che è una raccolta di test correlati.
- `it()`: Definisce un singolo caso di test all'interno della suite di test.
- `cy.visit()`: Naviga all'URL specificato.
- `cy.contains()`: Trova un elemento contenente il testo specificato.
- `.click()`: Clicca sull'elemento selezionato.
- `cy.url()`: Ottiene l'URL corrente della pagina.
- `.should()`: Esegue un'asserzione sullo stato dell'applicazione.
- `cy.get()`: Seleziona un elemento utilizzando un selettore CSS.
- `.type()`: Digita il testo nell'elemento selezionato.
- `.should('have.value', 'fake@email.com')`: Asserisce che il valore dell'elemento sia uguale a 'fake@email.com'.
Esegui questo test nel Cypress Test Runner per vederlo in azione. Dovresti vedere il browser navigare al sito web Cypress Kitchen Sink, fare clic sul link "type" e verificare l'URL.
Comandi Cypress
Cypress fornisce una vasta gamma di comandi per interagire con la tua applicazione. Ecco alcuni dei comandi più comunemente usati:
- `cy.visit(url)`: Naviga all'URL specificato.
- `cy.get(selector)`: Seleziona un elemento utilizzando un selettore CSS.
- `cy.contains(content)`: Seleziona un elemento contenente il testo specificato.
- `cy.click()`: Clicca sull'elemento selezionato.
- `cy.type(text)`: Digita il testo nell'elemento selezionato.
- `cy.clear()`: Cancella il contenuto di un elemento di input o textarea.
- `cy.submit()`: Invia un modulo.
- `cy.check()`: Seleziona una casella di controllo o un pulsante di opzione.
- `cy.uncheck()`: Deseleziona una casella di controllo.
- `cy.select(value)`: Seleziona un'opzione da un menu a tendina.
- `cy.scrollTo(position)`: Scorri la pagina fino alla posizione specificata.
- `cy.trigger(event)`: Attiva un evento DOM sull'elemento selezionato.
- `cy.request(url, options)`: Esegue una richiesta HTTP all'URL specificato.
- `cy.intercept(route, handler)`: Intercetta le richieste HTTP corrispondenti al percorso specificato.
- `cy.wait(time)`: Attende il tempo specificato.
- `cy.reload()`: Ricarica la pagina corrente.
- `cy.go(direction)`: Naviga alla pagina precedente o successiva nella cronologia del browser.
- `cy.url()`: Ottiene l'URL corrente della pagina.
- `cy.title()`: Ottiene il titolo della pagina.
- `cy.window()`: Ottiene l'oggetto window.
- `cy.document()`: Ottiene l'oggetto document.
- `cy.viewport(width, height)`: Imposta le dimensioni della viewport.
Questi sono solo alcuni dei tanti comandi disponibili in Cypress. Fare riferimento alla documentazione di Cypress per un elenco completo dei comandi e delle loro opzioni.
Asserzioni in Cypress
Le asserzioni vengono utilizzate per verificare il comportamento previsto della tua applicazione. Cypress fornisce un ricco set di asserzioni integrate che puoi utilizzare per controllare lo stato degli elementi, l'URL, il titolo e altro ancora. Le asserzioni vengono concatenate dopo i comandi Cypress utilizzando il metodo `.should()`.
Ecco alcuni esempi di asserzioni comuni:
- `.should('be.visible')`: Asserisce che un elemento è visibile.
- `.should('not.be.visible')`: Asserisce che un elemento non è visibile.
- `.should('be.enabled')`: Asserisce che un elemento è abilitato.
- `.should('be.disabled')`: Asserisce che un elemento è disabilitato.
- `.should('have.text', 'expected text')`: Asserisce che un elemento ha il testo specificato.
- `.should('contain', 'expected text')`: Asserisce che un elemento contiene il testo specificato.
- `.should('have.value', 'expected value')`: Asserisce che un elemento ha il valore specificato.
- `.should('have.class', 'expected class')`: Asserisce che un elemento ha la classe specificata.
- `.should('have.attr', 'attribute name', 'expected value')`: Asserisce che un elemento ha l'attributo e il valore specificati.
- `.should('have.css', 'css property', 'expected value')`: Asserisce che un elemento ha la proprietà CSS e il valore specificati.
- `.should('have.length', expected length)`: Asserisce che un elemento ha la lunghezza specificata (ad es. il numero di elementi in un elenco).
Puoi anche creare asserzioni personalizzate per soddisfare le tue esigenze specifiche.
Best practice per la scrittura di test Cypress
Seguire le best practice può aiutarti a scrivere test Cypress più gestibili, affidabili ed efficienti. Ecco alcuni consigli:
- Scrivi test chiari e concisi: Ogni test dovrebbe concentrarsi su una specifica funzionalità o scenario. Evita di scrivere test eccessivamente complessi che sono difficili da capire e mantenere.
- Usa nomi di test significativi: Dai ai tuoi test nomi descrittivi che indichino chiaramente cosa stanno testando.
- Evita di codificare valori in modo rigido: Usa variabili o file di configurazione per memorizzare valori che potrebbero cambiare nel tempo.
- Usa comandi personalizzati: Crea comandi personalizzati per incapsulare la logica riutilizzabile e rendere i tuoi test più leggibili.
- Isola i test: Ogni test dovrebbe essere indipendente dagli altri test. Evita di fare affidamento sullo stato dell'applicazione da test precedenti.
- Pulizia dopo i test: Reimposta lo stato dell'applicazione dopo ogni test per assicurarti che i test successivi partano da zero.
- Usa attributi dati: Usa attributi dati (ad esempio, `data-testid`) per selezionare gli elementi nei tuoi test. Gli attributi dati hanno meno probabilità di cambiare rispetto alle classi o agli ID CSS, rendendo i tuoi test più resistenti alle modifiche nell'interfaccia utente.
- Evita le attese esplicite: Cypress attende automaticamente che gli elementi diventino visibili o interagibili. Evita di utilizzare attese esplicite (ad esempio, `cy.wait()`) a meno che non sia assolutamente necessario.
- Testa i flussi utente: Concentrati sul test dei flussi utente piuttosto che sui singoli componenti. Questo ti aiuterà a garantire che la tua applicazione funzioni correttamente dalla prospettiva dell'utente.
- Esegui regolarmente i test: Integra i test Cypress nella tua pipeline CI/CD ed eseguili regolarmente per individuare i bug all'inizio del processo di sviluppo.
Tecniche avanzate di Cypress
Stubbing e Mocking
Cypress ti consente di simulare le richieste e le risposte di rete, consentendoti di simulare diversi scenari e testare la gestione degli errori della tua applicazione. Questo è particolarmente utile per testare funzionalità che si basano su API o servizi esterni.
Per simulare una richiesta di rete, puoi utilizzare il comando `cy.intercept()`. Ad esempio, il codice seguente simula una richiesta GET a `/api/users` e restituisce una risposta mock:
cy.intercept('GET', '/api/users', {
statusCode: 200,
body: [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Doe' }
]
}).as('getUsers')
Puoi quindi attendere la richiesta intercettata utilizzando `cy.wait('@getUsers')` e verificare che la tua applicazione gestisca correttamente la risposta mock.
Lavorare con Local Storage e Cookies
Cypress fornisce comandi per interagire con l'archiviazione locale e i cookie. Puoi usare questi comandi per impostare, ottenere e cancellare l'archiviazione locale e i cookie nei tuoi test.
Per impostare un elemento di archiviazione locale, puoi utilizzare il comando `cy.window()` per accedere all'oggetto window e quindi utilizzare il metodo `localStorage.setItem()`. Ad esempio:
cy.window().then((win) => {
win.localStorage.setItem('myKey', 'myValue')
})
Per ottenere un elemento di archiviazione locale, puoi utilizzare il comando `cy.window()` e quindi utilizzare il metodo `localStorage.getItem()`. Ad esempio:
cy.window().then((win) => {
const value = win.localStorage.getItem('myKey')
expect(value).to.equal('myValue')
})
Per impostare un cookie, puoi utilizzare il comando `cy.setCookie()`. Ad esempio:
cy.setCookie('myCookie', 'myCookieValue')
Per ottenere un cookie, puoi utilizzare il comando `cy.getCookie()`. Ad esempio:
cy.getCookie('myCookie').should('have.property', 'value', 'myCookieValue')
Gestione degli Upload di File
Cypress fornisce un plugin chiamato `cypress-file-upload` che semplifica gli upload di file nei tuoi test. Per installare il plugin, esegui il seguente comando:
npm install -D cypress-file-upload
Quindi, aggiungi la seguente riga al tuo file `cypress/support/commands.js`:
import 'cypress-file-upload';
Puoi quindi utilizzare il comando `cy.uploadFile()` per caricare un file. Ad esempio:
cy.get('input[type="file"]').attachFile('example.txt')
Lavorare con gli IFrames
Testare gli IFrames può essere complicato, ma Cypress fornisce un modo per interagire con essi. Puoi usare il comando `cy.frameLoaded()` per attendere il caricamento di un IFrame e quindi usare il comando `cy.iframe()` per ottenere l'oggetto document dell'IFrame.
cy.frameLoaded('#myIframe')
cy.iframe('#myIframe').find('button').click()
Cypress e Integrazione Continua/Distribuzione Continua (CI/CD)
L'integrazione di Cypress nella tua pipeline CI/CD è essenziale per garantire la qualità della tua applicazione. Puoi eseguire i test Cypress in modalità headless nel tuo ambiente CI/CD. Ecco come:
- Installa Cypress: Assicurati che Cypress sia installato come dipendenza nel tuo progetto.
- Configura CI/CD: Configura la tua pipeline CI/CD per eseguire i test Cypress dopo ogni build.
- Esegui Cypress in modalità headless: Usa il comando `cypress run` per eseguire i test Cypress in modalità headless.
Esempio di configurazione CI/CD (usando GitHub Actions):
name: Cypress Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Cypress run
uses: cypress-io/github-action@v5
with:
start: npm start
wait-on: 'http://localhost:3000'
Questa configurazione eseguirà i test Cypress ogni volta che il codice viene inviato al branch `main` o viene creata una pull request per il branch `main`. L'azione `cypress-io/github-action` semplifica il processo di esecuzione dei test Cypress in GitHub Actions.
Debug dei test Cypress
Cypress fornisce eccellenti strumenti di debug per aiutarti a identificare e risolvere i problemi nei tuoi test. Ecco alcuni suggerimenti per il debug dei test Cypress:
- Usa il Cypress Test Runner: Il Cypress Test Runner fornisce un'interfaccia visiva per eseguire e eseguire il debug dei tuoi test. Puoi scorrere i tuoi test un comando alla volta, ispezionare lo stato dell'applicazione e visualizzare messaggi di errore dettagliati.
- Usa il comando `cy.pause()`: Il comando `cy.pause()` mette in pausa l'esecuzione del tuo test e ti consente di ispezionare lo stato dell'applicazione negli strumenti per sviluppatori del browser.
- Usa il comando `cy.debug()`: Il comando `cy.debug()` stampa l'elemento selezionato sulla console, consentendoti di ispezionare le sue proprietà e attributi.
- Usa gli strumenti per sviluppatori del browser: Gli strumenti per sviluppatori del browser forniscono una grande quantità di informazioni sulla tua applicazione, tra cui il DOM, le richieste di rete e i log della console.
- Leggi attentamente i messaggi di errore: Cypress fornisce messaggi di errore dettagliati che possono aiutarti a identificare la causa dell'errore. Presta attenzione al messaggio di errore e allo stack trace.
Cypress vs. Altri Framework di Testing
Sebbene Cypress sia un potente framework di testing end-to-end, è essenziale capire come si confronta con altre opzioni popolari. Ecco una breve panoramica:
- Selenium: Selenium è un framework di testing dell'automazione ampiamente utilizzato. Sebbene flessibile e supportante più linguaggi, può essere complesso da configurare e mantenere. Cypress offre un'esperienza più semplice e più intuitiva per gli sviluppatori, in particolare per le applicazioni basate su JavaScript.
- Puppeteer: Puppeteer è una libreria Node che fornisce un'API di alto livello per il controllo di Chrome o Chromium headless. È eccellente per lo scraping e l'automazione delle attività del browser, ma potrebbe richiedere una configurazione più manuale rispetto a Cypress per il test end-to-end.
- Playwright: Playwright è un altro framework di automazione cross-browser sviluppato da Microsoft. Condivide somiglianze con Puppeteer, ma offre un supporto del browser più ampio. Cypress ha un debugger time-traveling unico e un'esperienza di test più integrata.
La scelta del framework dipende dalle esigenze e dai requisiti specifici del tuo progetto. Cypress è un'ottima scelta per le moderne applicazioni web che richiedono test end-to-end veloci, affidabili e intuitivi per gli sviluppatori.
Esempi reali di Cypress in azione
Esploriamo alcuni esempi reali di come Cypress può essere utilizzato per testare diversi tipi di applicazioni web:
Test di un'applicazione di e-commerce
Puoi usare Cypress per testare vari flussi utente in un'applicazione di e-commerce, come:
- Ricerca di prodotti
- Aggiunta di prodotti al carrello
- Checkout e ordine
- Gestione delle impostazioni dell'account
Ecco un esempio di un test Cypress che verifica che un utente possa aggiungere con successo un prodotto al carrello:
it('Aggiunge un prodotto al carrello', () => {
cy.visit('/products')
cy.get('.product-card').first().find('button').click()
cy.get('.cart-count').should('have.text', '1')
})
Test di un'applicazione di social media
Puoi usare Cypress per testare le interazioni degli utenti in un'applicazione di social media, come:
- Creazione di un nuovo post
- Mettere Mi piace a un post
- Commentare un post
- Seguire altri utenti
Ecco un esempio di un test Cypress che verifica che un utente possa creare con successo un nuovo post:
it('Crea un nuovo post', () => {
cy.visit('/profile')
cy.get('#new-post-textarea').type('Hello, world!')
cy.get('#submit-post-button').click()
cy.get('.post').first().should('contain', 'Hello, world!')
})
Test di un'applicazione bancaria
Per le applicazioni bancarie, Cypress può essere utilizzato per testare funzionalità critiche come:
- Login in modo sicuro
- Verifica dei saldi dei conti
- Trasferimento di fondi
- Gestione dei beneficiari
Un test per verificare un bonifico potrebbe essere simile a questo (con l'opportuna simulazione per la sicurezza):
it('Trasferisce fondi con successo', () => {
cy.visit('/transfer')
cy.get('#recipient-account').type('1234567890')
cy.get('#amount').type('100')
cy.intercept('POST', '/api/transfer', { statusCode: 200, body: { success: true } }).as('transfer')
cy.get('#transfer-button').click()
cy.wait('@transfer')
cy.get('.success-message').should('be.visible')
})
Conclusione
Cypress è un framework di testing end-to-end potente e versatile che può aiutarti a garantire la qualità e l'affidabilità delle tue applicazioni web. La sua API intuitiva per gli sviluppatori, le potenti funzionalità e le eccellenti prestazioni lo rendono una scelta popolare tra sviluppatori e ingegneri QA in tutto il mondo. Seguendo le best practice delineate in questa guida, puoi scrivere test Cypress efficaci che ti aiuteranno a individuare i bug all'inizio del processo di sviluppo e a fornire software di alta qualità ai tuoi utenti.
Poiché le applicazioni web continuano a evolversi, l'importanza del testing end-to-end non farà che aumentare. Abbracciare Cypress e integrarlo nel tuo flusso di lavoro di sviluppo ti consentirà di creare esperienze web più robuste, affidabili e facili da usare.