Test funzionali senza testa con selenio e PhantomJS

Costruiamo un sistema per l'esecuzione di test funzionali su applicazioni Web, utilizzando Selenium e PhantomJS. Il sistema risultante ci consentirà di scrivere semplici scenari di test in JavaScript e di testare questi scenari sia nei browser reali che in un simulatore senza testa.


Scelta dei componenti

L'aspetto negativo del Selenium è che richiede un desktop grafico completo per tutti i test.

Per iniziare, dobbiamo scegliere un controllo del browser o un motore di emulazione per simulare un utente finale. Per molto tempo, il giocatore principale in questo campo era il selenio, e lo è ancora. Selenium consente il controllo automatico dei browser reali su sistemi operativi reali, il che è il suo principale vantaggio: puoi essere assolutamente certo che i test rappresentino la realtà il più vicino possibile.

L'aspetto negativo del Selenium è che richiede un desktop grafico completo per tutti i test. Di conseguenza, i test possono rallentare. Tuttavia, Selenium può essere fantastico, se si dispone delle risorse necessarie per configurare macchine virtuali per diversi sistemi operativi e collegarle tutte insieme.

All'estremità opposta dello spettro c'è PhantomJS: un piccolo ma eccellente progetto, che esegue un motore WebKit con accesso JavaScript completo, ma senza la parte grafica. PhantomJS è un gioco da ragazzi da configurare, funziona su qualsiasi macchina ed è notevolmente più veloce.

Selenium ora può controllare PhantomJS nello stesso modo in cui lo fa con qualsiasi altro browser.

PhantomJS, essendo un WebKit completo, copre il 90% delle tue esigenze di test funzionali. Dopo tutto, se l'applicazione viene eseguita correttamente in WebKit, è probabile che venga eseguita correttamente in altri browser. Ovviamente, questo esclude Internet Explorer 6-8.

Tuttavia, poiché il tuo progetto diventa sempre più popolare, il restante 10% diventa un problema significativo. Se la tua suite di test funzionale è impostata direttamente su PhantomJS, sarebbe un problema riscrivere i test per il selenio.

Fortunatamente, recentemente, verso la fine del 2012, abbiamo ricevuto un regalo sotto forma di attacchi PhantomJS al selenio. In altre parole, Selenium ora può controllare PhantomJS nello stesso modo in cui utilizza qualsiasi altro browser.

Dato che Selenium, di per sé, non ha bisogno di alcuna configurazione complicata e può funzionare ovunque, possiamo utilizzare i collegamenti Selenium per controllare PhantomJS e coprire il 90% delle nostre esigenze di test. Se in seguito hai bisogno di test più potenti, puoi impostare connessioni browser aggiuntive a Selenium senza modificare una singola riga nel codice.

Pertanto, la nostra scelta per il motore del browser è Selenium con PhantomJS.

Descrivere i test

Il selenio offre legami nei più diffusi linguaggi di programmazione, quindi possiamo scegliere una lingua in base alle nostre esigenze. Questo è forse il pezzo più controverso di questo articolo: ritengo che JavaScript sia la scelta migliore per descrivere test funzionali per siti Web e applicazioni web.

  • Indipendentemente dalla tecnologia di back-end utilizzata, il front-end utilizzerà sempre JavaScript (Questo si applica anche se si utilizza un linguaggio che compila fino a vanilla JavaScript, come CoffeeScript o TypeScript.). In quanto tale, JavaScript sarà sempre una lingua comprensibile da almeno una persona nella tua squadra.
  • Quindi, considera la possibilità che i tuoi test funzionali vengano scritti da non programmatori. La popolarità di JavaScript sul front-end, combinata con l'espressività nella capacità di creare chiari linguaggi specifici del dominio, consente a più persone di scrivere test funzionali.
  • Infine, è naturale controllare un browser di test con JavaScript, dato che è altamente asincrono, ed è ciò su cui controlliamo il browser quotidianamente.

I collegamenti selenio per JavaScript sono chiamati, webdriverjs. Sebbene il progetto sia meno maturo dei driver ufficialmente supportati per Java, C #, Ruby e Python, tuttavia contiene già la maggior parte delle funzionalità di cui abbiamo bisogno.

Prova in esecuzione

Per gli scopi di questo articolo, sono stati selezionati Moka con Chai.

Infine, abbiamo bisogno di un test runner, o di un'applicazione per eseguire test per nome, e stampare piuttosto l'output, osservando quanti test hanno avuto esito positivo o negativo. Questo test runner dovrebbe anche offrire una libreria di asserzioni, che consente al codificatore di esprimere se un test ha esito positivo o negativo.

La scelta è assolutamente gratis qui. Esistono molti test runner di JavaScript, ma per gli scopi di questo articolo sono stati selezionati Mocha with Chai. Mocha offre una notevole quantità di flessibilità, un'ampia varietà di formati di output e la famosa sintassi simile a Jasmine. Chai ti consente di scrivere asserzioni descrittive simili a BDD.


Impostare

Ecco lo stack finale che utilizzeremo:

  1. Mocha - test runner
  2. Chai - libreria di asserzioni
  3. webdriverjs: associazioni di controllo del browser
  4. Selenio: astrazione del browser e fabbrica funzionante
  5. PhantomJS - browser headless veloce

Node.js e npm

Poiché la maggior parte del nostro stack è basata su JavaScript, abbiamo bisogno di node.js e npm. Entrambi sono strumenti comuni nella community e presumo che tu li abbia già impostati. In caso contrario, utilizzare il programma di installazione sul sito Web node.js. Non preoccuparti; se qualcosa va storto, ci sono un sacco di guide all'installazione del nodo disponibili sul web.

Mocha, Chai e webdriverjs

Tutti e tre questi possono essere installati, usando npm:

sudo npm install -g mocha chai webdriverjs

In alternativa, puoi installarli localmente nella directory in cui si trovano i tuoi test:

npm installa mocha chai webdriverjs

Selenio

Scarica Selenium Server. È distribuito come singolo vaso file, che si esegue semplicemente:

java -jar selenium-server-standalone-2.28.0.jar

Non appena esegui questo comando, avvia un server al quale il tuo codice di test si collegherà in seguito. Si noti che è necessario eseguire Selenium Server ogni volta che si eseguono i test.

PhantomJS

Versione rapida

Uso npm installare PhantomJS globalmente:

sudo npm install -g phantomjs

Altre opzioni

Richiediamo una nuova versione di PhantomJS - almeno 1.8. Ciò significa che i pacchetti forniti dal tuo gestore di pacchetti (apt-get, MacPort, ...) sarà probabilmente obsoleto.

È possibile installare utilizzando npm senza un'installazione globale o utilizzando altri metodi manualmente. In questo caso, tuttavia, dovrai dire a Selenium dove hai posizionato PhantomJS ogni volta che esegui il selenio:

PATH = "/ percorso / a / node_modules / phantomjs / bin: $ PATH" java -jar selenium-server-standalone-2.28.0.jar

Combinare tutto

Ora che abbiamo tutti i pezzi, dobbiamo mettere tutto insieme.

Ricorda: prima di eseguire qualsiasi test, devi eseguire Selenium Server:

java -jar selenium-server-standalone-2.28.0.jar

Selenium eseguirà internamente PhantomJS; non devi preoccuparti di questo.

Ora, dobbiamo connetterci al selenio dal nostro JavaScript. Ecco uno snippet di esempio, che avvierà una connessione a Selenium e avrà un oggetto pronto per controllare la nostra istanza Selenium:

// Usa webdriverjs per creare un client Selenium var client = require ('webdriverjs'). Remote (desiderateCapabilities: // Puoi scegliere altri browser // http://code.google.com/p/selenium/wiki/ DesiredCapabilities browserName: 'phantomjs', // webdriverjs ha un sacco di output che è generalmente inutile // Tuttavia, se qualcosa va storto, rimuovilo per vedere più dettagli logLevel: 'silent'); client.init ();

Ora possiamo descrivere i nostri test e usare il cliente variabile per controllare il browser. Un riferimento completo per l'API webdriverjs è disponibile nella documentazione, ma ecco un breve esempio:

client.url ('http://example.com/') client.getTitle (function (title) console.log ('Title is', title);); client.setValue ('# campo', 'valore'); client.submitForm (); client.end ();

Usiamo la sintassi Mocha e Chai per descrivere un test; testeremo alcune proprietà del example.com pagina web:

descrivere ('Test example.com', function () before (function (done) client.init () .url ('http://example.com', done);); describe ('Check homepage') , function () it ('dovrebbe vedere il titolo corretto', function (done) client.getTitle (function (title) expect (title) .to.have.string ('Esempio Domain'); done (); );); it ('dovrebbe vedere il corpo', function (done) client.getText ('p', function (p) expect (title) .to.have.string ('per esempi illustrativi nei documenti . '); done ();));); after (function (done) client.end (); done ();););

Potresti voler condividerlo cliente inizializzazione su molti file di test. Crea un piccolo modulo Node per inizializzarlo e importarlo in ogni file di test:

Client.js:

exports.client = require ('webdriverjs'). remote (// Settings;

test.js:

var client = require ('./ client'). client; var expect = require ('chai'). expect; // Esegui test

In esecuzione

Le suite di test Mocha vengono eseguite con moca binario. Se hai seguito questa guida e hai installato Mocha localmente, dovresti descrivere tu stesso un percorso completo per il binario: node_modules / moka / bin / moka.

Per impostazione predefinita, Mocha considera qualsiasi test che richiede più di due secondi come non riuscito. Dato che in realtà stiamo inizializzando un browser web e facendo una richiesta HTTP, dobbiamo aumentare questo timeout a 5 o 10 secondi:

node_modules / mocha / bin / mocha test.js -t 10000

Se tutto è andato secondo i piani, dovresti vedere un risultato come questo:

 . ✔ 1 test completato

I prossimi passi

Una volta raggiunti i risultati dei test funzionali desiderati, si consiglia di prendere in considerazione di migliorare ulteriormente la configurazione.

Due direzioni ovvie sono l'integrazione continua e il test del selenio distribuito.

Integrazione continua

Il tuo obiettivo dovrebbe essere quello di ridurre al minimo il tempo speso per l'esecuzione dei test.

Potresti voler utilizzare un server di integrazione continua completamente automatico, che eseguirà i test ogni volta che sarà necessario automaticamente e ti informerà se qualcosa va storto.

Nel mondo dell'open source, il ruolo di tale server è coperto da Jenkins CI: un servizio comodo, potente e facile da installare, che eseguirà i test ogni volta che sarà necessario, eseguirli in qualsiasi configurazione fornita e possibilmente eseguire molti più attività correlate alla build, come la distribuzione del codice su server remoti.

In alternativa, se ti senti avventuroso, potresti sperimentare un nuovo progetto, chiamato GitLab CI, che offre meno funzioni, ma sembra migliore ed è integrato con GitLab, un clone di GitHub ospitato autonomamente.

In ogni caso, il tuo obiettivo dovrebbe essere quello di ridurre al minimo il tempo speso nell'esecuzione dei test. Invece, i test dovrebbero essere eseguiti automaticamente e dovrebbero informarti solo se qualcosa va storto.

Griglia di selenio

Il selenio ha un numero di limiti di implementazione. Ad esempio, non è possibile eseguire più di alcuni browser sulla stessa macchina per essere testati con Selenium.

Inoltre, noterai che, una volta che hai molti test, eseguirli tutti può diventare un processo lungo. Sebbene l'integrazione continua in parte attenui questo problema, potresti comunque voler eseguire alcuni test in parallelo su macchine diverse.

Infine, noterai presto che desideri testare diversi browser su diversi sistemi operativi. E, mentre il tuo codice di test può, in teoria, parlare con diversi server Selenium, una volta cresciuti un po ', questa configurazione richiede la centralizzazione.

L'installazione della griglia di selenio cerca di fornire esattamente questo. Invece di avere un server Selenium per controllare un gruppo di browser su una macchina, hai un server Selenium, che controlla più nodi Selenium, ognuno dei quali controlla solo alcuni browser su un singolo sistema operativo.


Conclusione

Lo stack risultante, sebbene non banale, in realtà, è abbastanza semplice. L'aggiunta di PhantomJS alla fine del selenio ci consente di iniziare a utilizzare Selenium senza molti investimenti iniziali, come l'impostazione di server di test grafici.

L'utilizzo di JavaScript come motore di test garantisce che i nostri test siano mantenuti pertinenti nel contesto dello sviluppo web per il prossimo futuro.