Test e2e pronti per CI per Angular con Cypress e TypeScript in meno di 60 minuti

Questo articolo ha lo scopo di descrivere come è possibile impostare test end-to-end per Angular con Cypress incluso TypeScript. Scriverete i vostri primissimi test e2e e li renderete pronti per essere eseguiti su CircleCI come sistema di integrazione continua ad ogni aggiornamento del vostro repository.

I test end-to-end (abbreviato e2e) sono un tipo di test del software che convalida il sistema software insieme alla sua integrazione con interfacce esterne. Lo scopo del test end-to-end è quello di esercitare uno scenario completo simile alla produzione.

Fonte: https://www.guru99.com/end-to-end-testing.html.

Panoramica

  • Che cos’è Cypress?
  • Prequisiti
  • Impostazione di Cypress
  • Scrittura di alcuni test
  • Impostazione dell’integrazione continua
  • Conclusione e riferimenti

Ho un background di sviluppo frontend in Microsoft .NET & WPF e ricordo i tempi in cui valutavamo framework costosi per scrivere test end-to-end per i nostri progetti. Dopo un sacco di valutazioni e settimane, anche mesi di codice collante personalizzato e lo sviluppo di infrastrutture di test sopra gli strumenti esistenti, abbiamo finalmente ottenuto alcuni test e2e in esecuzione. Erano fragili, spesso fallivano a causa degli aggiustamenti manuali che dovevamo fare o dei problemi con i runner difettosi nella pipeline di integrazione continua.

Alcuni anni dopo con Angular e Protractor come default per i test e2e, eravamo ancora basati su oggetti pagina, Selenium Web Driver e i test continuavano ad essere piuttosto inaffidabili. Non erano necessari costosi framework commerciali e infrastrutture personalizzate. Ma era divertente scrivere test e2e? No.

Tuttavia ora siamo nel 2020 ed è arrivato il momento di far nascere nuovi eroi. 🚀

Cos’è Cypress?

Cypress promette test veloci, facili e affidabili per qualsiasi cosa che gira in un browser. Non è basato su Selenium Web Driver che utilizza connessioni di rete per interagire con il browser. Invece Cypress è un test runner che gira all’interno del tuo browser accanto alla tua applicazione web e quindi ha un controllo diretto su di essa.

Senza entrare in tutti i dettagli, questo non solo rende Cypress più veloce e affidabile, ma apre anche le porte a molte altre caratteristiche interessanti come

  • il debugging del viaggio nel tempo,
  • facili snapshotting e registrazione,
  • attese automatiche.

In cima a tutte le caratteristiche, Cypress ha una esperienza sviluppatore (DX) che è quasi senza rivali. Avete mai visto un messaggio nei log degli errori della vostra build fallita che vi dice esattamente cosa avete sbagliato, vi indica le giuste dipendenze da aggiungere e vi collega anche a un sito di documentazione esplicativa che descrive il problema? Questo è ciò che è Cypress. È costruito dagli sviluppatori per gli sviluppatori.

Errore di Cypress sul server di compilazione che ti dice come risolverlo

Di seguito, installeremo Cypress per un progetto Angular fresco creato con la CLI. Scriveremo alcuni test e2e e concluderemo con l’esecuzione di questi con un sistema di build automatico. Tutti questi passi non dovrebbero richiedere più di 60 minuti. Cerchiamo di mantenere i passi più brevi possibile, sfruttando strumenti esistenti come gli schemi di Angular, le librerie e i template comuni.

Prerequisiti

Questa guida presuppone che abbiate un progetto standard di app Angular 9. In caso contrario, potete crearne uno come fareste normalmente con la CLI di Angular. Se non avete la CLI installata globalmente, potete fare uso del comando npx che la installerà temporaneamente al volo:

npx @angular/cli new <app-name>

Impostare Cypress

Per impostare Cypress insieme a TypeScript il più velocemente possibile, facciamo uso di uno schema esistente sviluppato da BrieBug.

Nella root del tuo progetto Angular, puoi aprire il terminale e inserire il seguente comando:

ng add @briebug/cypress-schematic --addCypressTestScripts

Se la CLI non è installata globalmente, il comando ng potrebbe non essere disponibile direttamente. È possibile imporre l’uso del ng locale dal package.json:

npm run ng -- add @briebug/cypress-schematic # In case 'ng' could not be found

Possiamo tranquillamente rimuovere Protractor perché sarà completamente sostituito. Durante l’installazione sono stati scaricati alcuni binari perché Cypress viene fornito con un’interfaccia utente Electron-bundled come test runner interattivo.

Utilizzando il flag --addCypressTestScripts sono stati aggiunti due comodi script npm per rendere più confortevole il lavoro con Cypress. Uno per eseguire i test e2e senza testa e l’altro script che esegue i test con il runner Cypress UI:

 // package.json scripts "cy:run": "cypress run", "cy:open": "cypress open"

Se si dovesse eseguire uno di questi script standalone, il test fallirebbe perché cerca di indirizzare a http://localhost:4200 dove al momento non viene servito nulla. Per risolvere questo problema, dobbiamo aprire un secondo terminale e servire prima la nostra applicazione Angular con npm start.

Per fortuna lo schema ha adattato il comando e2e in modo che questo venga fatto automaticamente dal costruttore della CLI. Potete servire l’applicazione e avviare il test e2e utilizzando il seguente comando:

npm run e2e

Cypress rileverà che lo abbiamo lanciato per la prima volta. Verifica la sua installazione e aggiunge alcuni file di esempio iniziali. Dopo che l’UI si è aperta, possiamo vedere un test che è già stato creato per noi.

Cypress UI dopo cy:open

Selezionando il test lo eseguirà. Inizialmente il test fallirà perché non abbiamo testato correttamente qualcosa. Sistemeremo questo adesso.

Test fallito che non è ancora implementato

Scrittura di alcuni test

Come primo passo, come proposto dalle best practice di Cypress, impostiamo la nostra baseUrl globale, in modo da non doverla duplicare ad ogni esecuzione di test. Aggiungiamo quanto segue alla configurazione cypress.json:

// cypress.json{ "baseUrl": "http://localhost:4200"}

Dopo di che, scriviamo il nostro primissimo smoke test che controlla solo se il titolo predefinito dell’app è impostato sulla pagina iniziale di Angular. Quindi, cambiamo il contenuto del spec.ts con il seguente contenuto:

// spec.tsit('smoke test', () => { cy.visit('/'); cy.contains('cypress-e2e-testing-angular app is running!');});

Il test inizia facendo il routing alla nostra baseUrl e procede interrogando qualsiasi elemento che contiene il testo cypress-e2e-testing-angular app is running!.

Test dei flussi utente

Questo test dovrebbe già funzionare, ma scriviamone altri più interattivi. Poiché gli e2e sono intrinsecamente più lenti dei test unitari, va benissimo avere dei test e2e che modellano l’intero flusso utente di una funzione.

Per esempio, vogliamo controllare se alcune caratteristiche della pagina iniziale sono valide: La nostra pagina dovrebbe contenere il titolo e il testo ng generate nel terminale per impostazione predefinita, ma quando gli utenti fanno clic sul pulsante Angular Material, vogliamo assicurarci che il comando ng add corretto sia visualizzato nella vista del terminale sottostante.

Potete sostituire il contenuto del vostro file di test con questo:

// spec.tsdescribe('When Angular starting page is loaded', () => { beforeEach(() => { cy.visit('/'); }); it('has app title, shows proper command by default and reacts on command changes', () => { cy.contains('cypress-e2e-testing-angular'); cy.contains('.terminal', 'ng generate component xyz'); cy.contains('Angular Material').click(); cy.contains('.terminal', 'ng add @angular/material'); });});

Abbiamo rifatto la nostra suite di test aggiungendo un blocco describe per catturare tutti i test che vengono eseguiti quando la pagina iniziale viene caricata. Poiché visitiamo la baseUrl ogni volta, abbiamo spostato questo nella chiamata beforeEach. Infine abbiamo combinato i test di fumo di base con il test per la vista terminale sulla pagina iniziale.

È importante sapere che non dovreste memorizzare i risultati delle query di Cypress in variabili, ma invece lavorare con le chiusure. Inoltre, abbiamo selezionato gli elementi per classi CSS e contenuti di testo, che possono essere troppo fragili. Si raccomanda di usare gli attributi data- per selezionare gli elementi.

Cypress ha un sacco di grandi caratteristiche e possibilità. Non le copriremo tutte perché il nostro obiettivo è quello di concentrarci sul primo punto di partenza. La documentazione ufficiale è davvero buona e copre tutto su come interagire con gli elementi.

Se si esegue nuovamente questa suite di test, si dovrebbe vedere l’UI cliccare attraverso ogni scenario e tutti e tre i test dovrebbero passare questa volta. ✔✔✔

Eseguire la nostra prima suite di test Cypress con successo

Impostare l’integrazione continua

Ora che i nostri test vengono eseguiti localmente, diamo il via a una piccola pipeline CI (integrazione continua). Un buon modo per prepararsi a questo, è quello di creare degli script npm e combinarli in modo che il sistema di compilazione possa usare un unico script come punto di ingresso. Seguendo questo metodo, si possono provare i passi di CI localmente prima di spingerli online. Inoltre gli script npm sono piuttosto indipendenti da qualsiasi sistema di compilazione effettivo.

Su CI, dobbiamo avviare il nostro server in background e aspettare che faccia il bundle della nostra applicazione, il che potrebbe richiedere un po’ di tempo. Poi abbiamo bisogno di avviare il test runner Cypress, passare attraverso i test e spegnere il server quando i test finiscono. Fortunatamente possiamo fare tutto questo con una singola utility chiamata start-server-and-test come descritto nei documenti di Cypress:

npm install --save-dev start-server-and-test

Dopo che questo è installato, usiamo il servizio Angular che è attualmente dietro npm start e lo combiniamo con il comando headless cy:run:

 // package.json scripts "start": "ng serve", "cy:run": "cypress run", "e2e:ci": "start-server-and-test start http://localhost:4200 cy:run"

Si potrebbe sicuramente usare una build di produzione o costruire prima e servire l’app usando qualsiasi server http. Per amor di concisione, lascerò questi miglioramenti a voi.

Circle CI

Per il nostro esempio, abbiamo scelto CircleCI perché si integra molto bene con GitHub, è comunemente usato lì e ha un piano gratuito. Potete usare qualsiasi altro sistema CI come Jenkins o GitLab (con cui ho più esperienza). Dopo l’accesso a CircleCI e la connessione al nostro account GitHub, è possibile selezionare il repository e creare un nuovo progetto tramite la loro dashboard.

Per configurare la pipeline, si potrebbe scrivere un config.yml selezionando un modello e adattandolo alle proprie esigenze ed eventualmente eseguire lo script e2e. Fortunatamente Cypress ha una configurazione pronta all’uso (chiamata Orbs) per CircleCI che include già l’installazione delle dipendenze, il caching e così via. Prima di poterlo utilizzare, dobbiamo visitare le Impostazioni dell’organizzazione per abilitare i runner di terze parti.

# circleci/config.ymlversion: 2.1orbs: # This Orb includes the following: # - checkout current repository # - npm install with caching # - start the server # - wait for the server to respond # - run Cypress tests # - store videos and screenshots as artifacts on CircleCI cypress: cypress-io/cypress@1workflows: build: jobs: - cypress/run: start: npm start wait-on: 'http://localhost:4200' store_artifacts: true

La pipeline ha solo un lavoro: Eseguire tutti i test e2e. Controlla il ramo corrente, installa tutte le dipendenze incluso il caching, avvia il server dell’applicazione ed esegue i nostri test. Inoltre, i video (registrati di default) e gli screenshot (nel caso in cui i test falliscano) vengono caricati come artefatti CircleCI per ulteriori controlli.*

CircleCI Dashboard

Conclusione

I passi di questa guida sono piuttosto minimi. Potete usare il vostro progetto Angular esistente, potete cambiare la configurazione delle vostre suite di test Cypress e scrivere molti test più significativi. Inoltre, si possono definire script npm per diversi scenari e ambienti e, naturalmente, l’intera pipeline di compilazione può essere estesa con il linting, i test unitari, la costruzione e anche il deploy della vostra applicazione. Ciononostante, questo dovrebbe essere un primo passo che mostra quanto velocemente i test automatici end-to-end possano essere impostati al giorno d’oggi.

Aspettate di scrivere veri test Cypress per la vostra applicazione. Ti divertirai!

Mind blown gif

Spero che anche tu possa trovare del valore in questo articolo. Se avete domande o osservazioni, fatemelo sapere. Il tuo feedback è molto gradito!

Puoi trovare le fonti per questa guida su GitHub:

MrCube42 / cypress-e2e-testing-angular

Esempio di app Angular 9 utilizzando Cypress per i test end-to-end.

CypressE2eTestingAngular

Questo progetto è stato generato con Angular CLI versione 9.0.6.

Server di sviluppo

Esegui ng serve per un server dev. Naviga verso http://localhost:4200/. L’applicazione si ricaricherà automaticamente se cambierai uno qualsiasi dei file sorgente.

Code scaffolding

Esegui ng generate component component-name per generare un nuovo componente. Puoi anche usare ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build per costruire il progetto. Gli artefatti di costruzione saranno memorizzati nella directory dist/. Usa il flag --prod per una build di produzione.

Running unit tests

Run ng test per eseguire i test unitari tramite Karma.

Running end-to-end tests

Run npm run e2e per eseguire i test end-to-end tramite Cypress.

Aiuto ulteriore

Per ottenere ulteriore aiuto su Angular CLI usa ng help o vai a controllare il README di Angular CLI.

Leave a Reply