Code, Learn

Tips & Tricks per Cypress.io

3 Luglio 2020 - 4 minuti di lettura

Nell’ultimo anno mi è capitato di lavorare con Cypress.io (1), un nuovo all-in-one testing framework per velocizzare la scrittura e l’esecuzione di test a tutti i livelli (da unit test a end-to-end test). Un tool relativamente nuovo, che si sta pian piano imponendo nella comunità abituata all’utilizzo della suite Selenium (2).

Spinto dalla curiosità e sete di conoscenza, il 21 Maggio ho deciso di seguire un webinar specifico dal titolo “Tips and Tricks for Writing Cypress Tests”, organizzato dal neonato gruppo Meetup Cypress.io UK Community (3). Una comunità che ha come scopo la condivisione di esperienze e best practices per aiutare altri sviluppatori, tester e QA.

Nei prossimi paragrafi vorrei condividervi quanto appreso dal talk curato da Xin Wang, Test Automation Engineer per News UK.

Per ulteriori approfondimenti sul suo intervento, potete consultare le slide (4) e il video (5).

Buona lettura.

Disclaimer

I contenuti di questo articolo presuppongono una conoscenza di base di Cypress.io. Il mio consiglio è seguire la documentazione ufficiale (6), molto ben organizzata, esaustiva e chiara.

Qualora voleste mettere fin da subito le mani nel vasetto della marmellata, vi suggerisco la lettura dell’articolo “Cypress Tutorial for Beginners: Getting started with End to End Testing(7) di Valentino Gagliardi, che vi guida passo passo dall’installazione del framework alla scrittura ed esecuzione dei test su di una semplice pagina HTML.

Setup di più file di configurazione

Come sappiamo attraverso il file cypress.json si configurano tutte le variabili d’ambiente per i nostri test. Qualora volessimo eseguire i test su più ambienti o per differenti scopi il suggerimento è crearne tanti quanti ne servono.

Dal momento che questi file di configurazione possono contenere informazioni che non si vogliono condividere, decidete se è il caso di committarli o meno.

E’ bene nominare ogni file seguendo la regola cypress.env.json. Ad esempio si potrebbero avere:

  • cypress.dev.json
  • cypress.dev.mobile.json
  • cypress.staging.json
  • cypress.dev.visual.json

Questo perché magari l’url della app da testare cambia in ambiente di stage, o perché per fare test per la versione mobile occorrono altre variabili di configurazione.

Per comunicare al framework quale configurazione usare, Xin ci mostra una soluzione in 2 passaggi adottata dal suo team. Nel file package.json bisogna aggiungere tanti script ad-hoc quanti sono i file, ad esempio:

"cy:run:dev": "cypress run --env configFile=dev --headless --browser chrome"

Con questo comando si specifica l’esecuzione dei test in headless mode usando il browser Chrome. La variabile d’ambiente configFile=dev serve per dire quale file di configurazione prendere, nell’esempio cypress.dev.json.

Nel file index.js nella directory plugins aggiungere il codice per un plugin appunto che ritorna il file di configurazione specifico se viene trovato oppure quello di default cypress.json:

Eseguire sottoinsieme di test

Può capitare di dover eseguire un insieme di test in certe condizioni, la prima cosa che viene in mente è fare un copia-incolla della cartella integration e quindi modificare la suite di test. Non proprio il massimo.

Un’idea potrebbe essere di realizzare una funzione di filtro che wrappa il test.

const TestFilter = (definedTags, runTest) => {
  if (Cypress.env('TEST_TAGS')) {
    const tags = Cypress.env('TEST_TAGS').split(',');
    const isFound = definedTags.some(definedTag => tags.includes(definedTag));
    if (isFound) {
      runTest();
    }
  }
};

export default TestFilter;

La funzione prende come argomento una variabile d’ambiente (ad esempio TEST_TAGS) salvata, come tutte, nel file di configurazione. Se la variabile viene trovata per il test, allora il test viene eseguito per la condizione specificata nella variabile.
Dopo aver importato la funzione nella suite di test, bisognerà appunto usarla passando le 2 variabili, quindi l’array di tag e il test in esame:

import TestFilter from "../support/test-filter";

TestFilter(['dev'], () => {
  it('should have the correct feed', () => {
    const teaserBlocks = data.body.blocks.filter(block => block.type === 'teaser-block');
    teaserBlocks.forEach(block => block.teasers.forEach(teaser => 
      expect(teaser.topic.feed).to.equal(collection.feed)));
  });
});

Da riga di comando ovviamente bisogna passare la variabile d’ambiente a Cypress:

"cy:run:dev": "TEST_TAGS=dev cypress run --env configFile=dev"

Lavorare con iFrame

Se vi è già capitato di testare elementi contenuti all’interno di iFrame, immagino sappiate quanto possa essere tediante. Per fortuna qualcuno ha sollevato il problema, e ad oggi c’è una issue aperta (8) l’11 Maggio 2016 ma non ancora chiusa…ciò non vuol dire che non si possa lavorare con gli iFrame, anzi.

Xin ci mostra la soluzione che hanno implementato per ovviare ai problemi di cross-domain iFrame, ovvero problemi di comunicazione tra iFrame quando il dominio cambia e quindi non possono più interagire tra loro (ad esempio eseguire codice Javascript o modificare l’albero DOM).

Il primo passo è quello di abilitare il cross-domain iFrame settando "chromeWebSecurity": false nel file cypress.json,

Dopodiché è possibile reperire elementi del nostro iFrame usando i comandi:

  • cy.get()
  • cy.find()
  • cy.wrap()

Di seguito vi propongo il codice del comando clickIframeElement implementato da Xin e il suo team:

Cypress.Commands.add("clickIframeElement", selector => {
  cy.get("iframe").then($iframe => {
  const doc = $iframe.contents();
  cy.wrap(doc.find(selector))
    .first()
    .click({ force: true });
  });
});

Per ulteriori approfondimenti sul come lavorare con gli IFrame, rimando all’articolo (9) nel blog ufficiale.

Articolo scritto da