Integrazione dei test Cypress con Docker, Buildkite e CICD #frontend@twiliosendgrid
Pubblicato: 2020-12-30Abbiamo scritto molti test Cypress end-to-end (E2E) per verificare che le nostre applicazioni web funzionino ancora come previsto con il back-end. Dopo aver scritto questi test di automazione del browser, vorremmo che questi test Cypress venissero sempre eseguiti o attivati in qualche modo come i nostri unit test prima di unire il codice e distribuirlo in determinati ambienti. Questo ci ha portato a voler eseguire i nostri test Cypress in un container Docker da integrare con il nostro provider di integrazione continua (CI) e le macchine che utilizziamo nel cloud per eseguire questi container.
Quando si tratta di flussi di distribuzione, utilizziamo Buildkite come nostro provider CI. Questo ci consente di generare una build di passaggi automatizzati per la nostra applicazione in una pipeline Buildkite quando prevediamo di spostare il codice su tutta la linea. Per più contesto, una pipeline è un luogo solitamente legato al repository di un'applicazione in cui possiamo esaminare build o attivare build con determinati passaggi da eseguire quando crei richieste pull, esegui il push di nuove modifiche al codice, unisci codice da master e distribuisci in ambienti diversi . Creiamo più pipeline per scopi separati, ad esempio per l'implementazione, test Cypress attivati e test Cypress specifici eseguiti in base a una pianificazione.
Questo post del blog presuppone che tu abbia già scritto test Cypress in precedenza e che alcuni test siano in esecuzione, ma vorresti idee su come eseguire questi test tutto il tempo nei tuoi flussi di sviluppo e distribuzione. Se desideri invece una panoramica sulla scrittura dei test Cypress, puoi dare un'occhiata a questo precedente post sul blog e poi rivisitarlo quando hai qualcosa da eseguire.
Il nostro obiettivo è illustrarti idee su come integrare i test Cypress in un container Docker con il tuo provider CI, dando un'occhiata a come l'abbiamo fatto con Docker Compose e Buildkite nella nostra pipeline di distribuzione. Queste idee possono essere ampliate nella tua infrastruttura per le strategie, i comandi e le variabili di ambiente da applicare quando si attivano i test Cypress.
Il nostro flusso CICD standard
Nel nostro flusso di sviluppo e distribuzione standard, abbiamo impostato due pipeline:
- Il primo gestisce i nostri passaggi di distribuzione per quando eseguiamo il push del codice.
- Il secondo fa sì che i nostri test Cypress vengano eseguiti in parallelo e vengano registrati. Il successo o il fallimento di questa operazione influiscono sulla pipeline di distribuzione.
Nella nostra pipeline di distribuzione, creiamo le risorse delle nostre applicazioni Web, eseguiamo unit test e disponiamo di passaggi per attivare test Cypress selezionati prima della distribuzione in ciascun ambiente. Ci assicuriamo che passino prima di annullare la possibilità di eseguire un'apertura a pulsante. Questi test Cypress attivati nella seconda pipeline vengono eseguiti anche in un contenitore Docker e sono collegati al Cypress Dashboard a pagamento tramite una chiave di registrazione in modo da poter guardare indietro ai video, agli screenshot e all'output della console da quei test Cypress per eseguire il debug di eventuali problemi.
Utilizzando gli input selezionati di Buildkite , abbiamo ideato una dinamica, scegli la tua avventura in modo che gli utenti possano selezionare "Sì" o "No" per decidere quali cartelle delle specifiche Cypress eseguire e verificare mentre inseriamo più codice. La risposta predefinita sarebbe "No" per tutte le opzioni, ma il valore di "Sì" sarebbe il percorso glob della cartella delle specifiche di Cypress.
A volte, non vogliamo eseguire tutti i test Cypress se la nostra modifica al codice non influisce su altre pagine. Noi, invece, vogliamo solo innescare i test che sappiamo saranno interessati. Potrebbe anche essere necessario distribuire una soluzione rapida alla produzione per un problema di bug urgente poiché ci sentiamo abbastanza sicuri da non eseguire i nostri test Cypress che possono richiedere da 0 a 10 minuti a seconda di quanti test attiviamo. Forniamo un esempio sia visivamente che nei passaggi YML per questa parte.
Successivamente, abbiamo implementato il nostro script Bash chiamato runCypress.sh
da eseguire dopo quel passaggio di selezione per analizzare i valori "Sì" o "No" selezionati. Facciamo questo per formare un elenco di percorsi di specifiche separati da virgole da eseguire e aggiungere come opzione, --spec
, al nostro eventuale comando Cypress che viene eseguito in un contenitore Docker in una pipeline attivata. Esportiamo variabili di ambiente come l'elenco formato di specifiche in "CYPRESS_SPECS" e l'ambiente di test corrente in "CYPRESS_TEST_ENV" da utilizzare nella pipeline che stiamo attivando alla fine dello script con buildkite-agent pipeline upload "$DIRNAME"/triggerCypress.yml
.
Potresti aver notato come esportiamo anche una variabile di ambiente "ASYNC". In Buildkite, puoi scegliere di fare in modo che un passaggio di build attivato sia bloccante o non bloccante in termini di successo o fallimento. Se "ASYNC" è impostato su true, i passaggi della pipeline di distribuzione principale continueranno a essere eseguiti e non attenderanno il completamento dei test Cypress attivati in una pipeline diversa. L'esito positivo o negativo della pipeline non influisce sull'esito positivo o negativo della pipeline di distribuzione.
Se "ASYNC" è impostato su false, i passaggi principali della pipeline di distribuzione verranno bloccati fino al termine dei test Cypress attivati in una pipeline diversa. Il successo o il fallimento della build attivata porta al successo o al fallimento generale della pipeline di distribuzione da cui riprende dopo.
Quando il nostro codice è ancora in un ramo di funzionalità con una richiesta pull aperta, ci piace inviare più modifiche, attivare alcuni test Cypress e vedere come si comportano le cose. Tuttavia, non vogliamo sempre bloccare l'esecuzione del resto dei passaggi della pipeline di distribuzione se i test attivati falliscono poiché ci sono potenzialmente più modifiche lungo il percorso. In questo scenario, impostiamo "ASYNC" su false per non bloccare se i test Cypress falliscono. Nel caso in cui abbiamo già unito la nostra richiesta pull in master e distribuita allo staging ma desideriamo attivare i test Cypress prima di distribuirli alla produzione, abbiamo impostato "ASYNC" su true poiché vogliamo che i test Cypress superino sempre prima di passare alla produzione .
Tornando a runCypress.sh
, ricordiamo che lo script attiva la seconda pipeline per l'esecuzione chiamando il file triggerCypress.yml
con i valori delle variabili di ambiente assegnati. Il file triggerCypress.yml
è simile a questo. Noterai che il passaggio "trigger" e l'interpolazione dei valori nei messaggi di compilazione sono utili per il debug e i nomi dinamici dei passaggi.
Sia che attiviamo i test Cypress per l'esecuzione dalla nostra pipeline di distribuzione a una pipeline di trigger separata o che eseguiamo i test Cypress in base a una pianificazione in una pipeline dedicata, seguiamo e riutilizziamo gli stessi passaggi modificando solo i valori delle variabili di ambiente.
Questi passaggi implicano:
- Creazione dell'immagine Docker con un tag più recente e un tag di versione univoco
- Spingere l'immagine Docker nel nostro registro privato
- Tirando verso il basso la stessa immagine per eseguire i nostri test Cypress in base ai valori delle nostre variabili di ambiente in un contenitore Docker
Questi passaggi sono descritti in un file pipeline.cypress.yml
in questo modo:
Quando attiviamo l'esecuzione dei test Cypress, verrà avviata una build separata nella pipeline di trigger Cypress. In base al successo o al fallimento della build, l'esecuzione del test di Cypress bloccherà o ci consentirà di eseguire la distribuzione in produzione quando si passa dallo staging alla produzione per le build del ramo principale.
Facendo clic sul passaggio "Cipresso attivato/integrazione/..." si accede alla build della pipeline attivata con una vista come questa per vedere come sono andati i test.
Se sei curioso di sapere come è collegata la parte Docker, i nostri Dockerfile.cypress
e docker-compose.cypress.yml
utilizzano quelle variabili di ambiente esportate dalle nostre pipeline per quindi utilizzare il comando Cypress corretto dal package.json
della nostra applicazione che punta a destra ambiente di test ed eseguire i file delle specifiche selezionati. I frammenti di seguito mostrano il nostro approccio generale che puoi ampliare e migliorare per essere più flessibile.
Al di fuori dei test eseguiti durante i nostri consueti cicli di integrazione e distribuzione, abbiamo creato pipeline Buildkite dedicate. Queste pipeline vengono eseguite in base a una pianificazione per test importanti sul nostro ambiente di staging per garantire che i nostri servizi front-end e back-end funzionino correttamente. Abbiamo riutilizzato passaggi della pipeline simili, modificato alcuni valori di variabili di ambiente nelle impostazioni della pipeline Buildkite e impostato una pianificazione cron da eseguire a un'ora pianificata. Questo ci aiuta a rilevare molti bug e problemi con l'ambiente di staging mentre continuiamo a monitorare quanto bene stanno andando i nostri test e se qualcosa a valle o dal nostro stesso codice push potrebbe aver portato a test non riusciti.
Parallelizzazione
Utilizziamo anche il flag di parallelizzazione per sfruttare il numero di macchine AWS che possiamo avviare dalla nostra coda di agenti di compilazione configurata dal nostro team operativo. Con questo flag di parallelizzazione, Cypress fa apparire automaticamente un certo numero di macchine in base al numero che abbiamo impostato nella proprietà "parallelismo" di Buildkite.
Siamo stati in grado di eseguire oltre 200 test in circa 5 minuti per uno dei nostri repository di applicazioni.
Quindi distribuisce tutti i test Cypress da eseguire in parallelo su quelle macchine mantenendo la registrazione di ciascuno dei test per un'esecuzione di build specifica. Ciò ha aumentato notevolmente i tempi di esecuzione dei nostri test!
Ecco alcuni suggerimenti per la parallelizzazione dei test Cypress:
- Segui i suggerimenti nel servizio dashboard per il numero ottimale di macchine e imposta il numero di macchine in una variabile di ambiente per la flessibilità nelle pipeline.
- Dividi in file di test più piccoli, in particolare suddividendo i test più lunghi in blocchi che possiamo parallelizzare meglio tra le macchine.
- Assicurati che i tuoi test Cypress siano isolati e non si influenzino a vicenda o non dipendano l'uno dall'altro. Quando hai a che fare con l'aggiornamento, la creazione o l'eliminazione di flussi correlati, usa utenti e risorse di dati separati per evitare che i test si scontrino tra loro e si imbattono in condizioni di gara. I file di test possono essere eseguiti in qualsiasi ordine, quindi assicurati che non sia un problema durante l'esecuzione di tutti i test.
- Per Buildkite, ricorda di passare il valore della variabile di ambiente dell'ID build Buildkite
--ci-build-id
oltre all'opzioneparallel
in modo che sappia a quale esecuzione di build univoca associarsi durante la parallelizzazione dei test tra le macchine.
Revisionare:
Per collegare i tuoi test Cypress al tuo provider CI come Buildkite, dovrai:
- Crea un'immagine Docker con il codice dell'applicazione, utilizzando l'immagine di base Cypress necessaria e le dipendenze necessarie per eseguire i test in un ambiente Node su determinati browser.
- Spingi la tua immagine Docker su un registro con determinati tag
- Abbassa la stessa immagine in un passaggio successivo
- Esegui i tuoi test Cypress in modalità headless e con chiavi di registrazione se stai utilizzando il servizio Cypress Dashboard.
- Imposta diversi valori delle variabili di ambiente e collegali ai comandi che esegui per Cypress per attivare i test Cypress selezionati rispetto a un determinato ambiente di test in quei contenitori Docker.
Questi passaggi generali possono essere riutilizzati e applicati ai test Cypress eseguiti in base a una pianificazione e ad altri casi d'uso, come l'attivazione di test da eseguire su browser selezionati oltre alle pipeline di distribuzione. La chiave è sfruttare le capacità del provider della CI e impostare i comandi in modo che siano flessibili e configurabili in base ai valori delle variabili di ambiente.
Imposta i tuoi comandi in modo che siano flessibili e configurabili in base ai valori delle variabili di ambiente.
Dopo aver eseguito i test in Docker con il tuo provider CI (e se paghi per il servizio Dashboard), puoi sfruttare la parallelizzazione dei test su più macchine. Potrebbe essere necessario modificare i test e le risorse esistenti in modo che non dipendano da un altro per evitare che i test si calpestino a vicenda.
Abbiamo anche discusso di idee che puoi provare tu stesso, come la creazione di una suite di test per convalidare la tua API di back-end o l'attivazione di test da eseguire su un browser di tua scelta. Ci sono anche altri modi per impostare l'integrazione continua qui nei documenti Cypress .
Inoltre, è importante eseguire questi test Cypress durante i flussi di distribuzione o gli intervalli pianificati per assicurarsi che gli ambienti di sviluppo funzionino sempre come previsto. Ci sono state innumerevoli volte in cui i nostri test Cypress hanno rilevato problemi relativi ai servizi di backend downstream che erano inattivi o modificati in qualche modo, manifestandosi in errori dell'applicazione frontend. In particolare, ci hanno salvato da bug imprevisti nelle nostre pagine Web dopo che abbiamo rilasciato nuove modifiche al codice React.
Mantenere i test che superano e monitorare diligentemente i test non riusciti nei nostri ambienti di test portano a meno ticket di supporto e clienti più soddisfatti in produzione. Mantenere una suite sana e stabile di test Cypress in esecuzione quando si inviano nuove modifiche al codice offre maggiore sicurezza che le cose funzionino bene e consigliamo a te e ai tuoi team di fare lo stesso con i test di Cypress.
Per ulteriori risorse sui test Cypress, consulta i seguenti articoli:
- Cosa considerare quando si scrivono test E2E
- Panoramica di 1.000 piedi sulla scrittura di test di cipresso
- TypeScript Tutte le cose nei tuoi test Cypress
- Gestire i flussi di posta elettronica nei test Cypress
- Idee per configurare, organizzare e consolidare i test Cypress