Test di JavaScript con PhantomJS

Non penso di doverti convincere che testare il tuo codice JavaScript è una buona idea. Ma a volte può risultare noioso testare il codice JavaScript che richiede un DOM. Ciò significa che è necessario testare il codice nel browser e non è possibile utilizzare il terminale, giusto? Sbagliato, in realtà: inserisci PhantomJS.


Cosa è esattamente PhantomJS? Bene, ecco una descrizione del sito Web di PhantomJS:

PhantomJS è un WebKit senza testa con API JavaScript.

Come sai, Webkit è il motore di layout utilizzato da Chrome, Safari e altri browser di nicchia. Quindi PhantomJS è un browser, ma un browser senza testa. Ciò significa che le pagine Web renderizzate non vengono mai effettivamente visualizzate. Questo può sembrare strano per te; quindi puoi pensarlo come un browser programmabile per il terminale. Vedremo un esempio semplice in un minuto, ma prima dobbiamo installare PhantomJS.


Installazione di PhantomJS

Installare PhantomJS è in realtà piuttosto semplice: è solo un singolo binario che si scarica e si conficca nel percorso del terminale. Nella pagina di download di PhantomJS, scegli il tuo sistema operativo e scarica il pacchetto corretto. Quindi sposta il file binario dal pacchetto scaricato in una directory all'interno del percorso del terminale (mi piace inserire questo tipo di cose ~ / Bin).

Se sei su Mac OS X, c'è un modo più semplice per installare PhantomJS (e questo è in realtà il metodo che ho usato). Basta usare Homebrew, come questo:

brew update & brew install phantomjs

Ora dovresti avere PhantomJS installato. Puoi ricontrollare l'installazione eseguendo questo:

phantomjs --version

Sto vedendo 1.7.0; tu?


Un piccolo esempio

Iniziamo con un piccolo esempio.

simple.js
console.log ("siamo in grado di registrare cose."); funzione add (a, b) return a + b;  conslole.log ("Possiamo eseguire anche regolare JS:", add (1, 2)); phantom.exit ();

Vai avanti ed esegui questo codice inviando il seguente comando:

phantomjs simple.js

Dovresti vedere l'output dei due console.log linee nella finestra del terminale.

Certo, questo è semplice, ma è un buon punto: PhantomJS può eseguire JavaScript proprio come un browser. Tuttavia, questo esempio non ha alcun codice specifico di PhantomJS ... beh, a parte l'ultima riga. Questa è una linea importante per ogni script PhantomJS perché esce dallo script. Questo potrebbe non avere senso qui, ma ricorda che JavaScript non viene sempre eseguito in modo lineare. Ad esempio, potresti voler mettere il Uscita() chiama una funzione di callback.

Diamo un'occhiata ad un esempio più complesso.


Caricamento delle pagine

Utilizzando l'API PhantomJS, possiamo effettivamente caricare qualsiasi URL e lavorare con la pagina da due punti di vista:

  • come JavaScript nella pagina.
  • come utente che guarda la pagina.

Iniziamo scegliendo di caricare una pagina. Crea un nuovo file di script e aggiungi il seguente codice:

script.js
var page = require ('pagina web'). create (); page.open ('http://net.tutsplus.com', funzione (s) console.log (s); phantom.exit (););

Iniziamo caricando PhantomJS ' pagina web modulo e creazione di un oggetto pagina web. Quindi chiamiamo il Aperto metodo, passandogli un URL e una funzione di callback; è all'interno di questa funzione di callback che possiamo interagire con la pagina attuale. Nell'esempio sopra, registriamo semplicemente lo stato della richiesta, fornito dal parametro della funzione di callback. Se si esegue questo script (con phantomjs script.js), dovresti ottenere "successo" stampato nel terminale.

Ma rendiamo questo più interessante caricando una pagina e eseguendo alcuni JavaScript su di essa. Iniziamo con il codice sopra, ma a questo punto effettuiamo una chiamata page.evaluate:

page.open ('http://net.tutsplus.com', function () var title = page.evaluate (function () var posts = document.getElementsByClassName ("post"); post [0]. stile. backgroundColor = "# 000000"; return document.title;); page.clipRect = top: 0, left: 0, width: 600, height: 700; page.render (title + ".png"); phantom .Uscita(); );

PhantomJS è un browser, ma un browser senza testa.

La funzione che passiamo a page.evaluate viene eseguito come JavaScript nella pagina Web caricata. In questo caso, troviamo tutti gli elementi con il inviare classe; quindi, impostiamo lo sfondo del primo post in nero. Alla fine, restituiamo il titolo del documento. Questa è una bella funzionalità, che restituisce un valore dal nostro valutare richiamata e assegnandola a una variabile (in questo caso, titolo).

Quindi, impostiamo il clipRect sulla pagina; queste sono le dimensioni per lo screenshot che prendiamo con rendere metodo. Come puoi vedere, impostiamo il superiore e sinistra valori per impostare il punto di partenza e abbiamo anche impostato a larghezza e altezza. Infine, chiamiamo page.render, passandogli un nome per il file (il titolo variabile). Quindi, finiamo chiamando phantom.exit ().

Vai avanti ed esegui questo script, e dovresti avere un'immagine simile a questa:

Puoi vedere entrambi i lati della moneta PhantomJS qui: possiamo eseguire JavaScript dall'interno della pagina, e anche eseguire dall'esterno, sull'istanza stessa della pagina.

Questo è stato divertente, ma non incredibilmente utile. Concentriamoci sull'utilizzo di PhantomJS durante il test del nostro JavaScript relativo al DOM.


Test con PhantomJS

Yeoman usa PhantomJS nella sua procedura di test, ed è praticamente senza cuciture.

Per un sacco di codice JavaScript, puoi testare senza bisogno di un DOM, ma ci sono momenti in cui i tuoi test devono lavorare con elementi HTML. Se sei come me e preferisci eseguire test sulla riga di comando, è qui che entra in gioco PhantomJS.

Naturalmente, PhantomJS non è una libreria di test, ma molte delle altre librerie di test popolari possono essere eseguite su PhantomJS. Come puoi vedere dalla pagina wiki di PhantomJS sui test senza testa, i runner di test di PhantomJS sono disponibili per quasi tutte le librerie di test che potresti voler utilizzare. Diamo un'occhiata a come usare PhantomJS con Jasmine e Mocha.

In primo luogo, Jasmine e un disclaimer: non c'è un buon corridore di PhantomJS per Jasmine in questo momento. Se usi Windows e Visual Studio, dovresti controllare Chutzpah, e gli sviluppatori di Rails dovrebbero provare guard-jasmine. Ma a parte questo, il supporto di Jasmine + PhantomJS è scarso.

Per questo motivo, ti consiglio di usare Mocha per i test relativi al DOM.

PERÒ.

È possibile che tu abbia già un progetto utilizzando Jasmine e desideri utilizzarlo con PhantomJS. Un progetto, fantasma-gelsomino, richiede un po 'di lavoro da impostare, ma dovrebbe fare il trucco.

Iniziamo con una serie di test JasmineJS. Scarica il codice per questo tutorial (link in alto), e controlla il jasmine-starter cartella. Vedrai che abbiamo un singolo tests.js file che crea un elemento DOM, imposta alcune proprietà e lo aggiunge al corpo. Quindi, eseguiamo alcuni test Jasmine per garantire che il processo abbia funzionato correttamente. Ecco il contenuto di quel file:

tests.js
descrivere ("DOM Tests", function () var el = document.createElement ("div"); el.id = "myDiv"; el.innerHTML = "Ciao!"; el.style.background = "#ccc "; document.body.appendChild (el); var myEl = document.getElementById ('myDiv'); it (" è nel DOM ", function () expect (myEl) .not.toBeNull ();); ("è un figlio del corpo", function () expect (myEl.parentElement) .toBe (document.body);); it ("ha il testo giusto", function () expect (myEl.innerHTML ) .toEqual ("Ciao!");); it ("ha lo sfondo giusto", function () expect (myEl.style.background) .toEqual ("rgb (204, 204, 204)"); ););

Il SpecRunner.html il file è abbastanza disponibile; l'unica differenza è che ho spostato i tag dello script nel corpo per garantire che il DOM venga caricato completamente prima dell'esecuzione dei test. Puoi aprire il file in un browser e vedere che tutti i test passano bene.

Passiamo questo progetto a PhantomJS. In primo luogo, clonare il progetto fantasma-gelsomino:

git clone git: //github.com/jcarver989/phantom-jasmine.git

Questo progetto non è organizzato come potrebbe essere, ma ci sono due parti importanti che ti servono:

  • il corridore PhantomJS (che fa usare a Jasmine un DOM PhantomJS).
  • il reporter della console Jasmine (che fornisce l'output della console).

Entrambi questi file risiedono nel lib cartella; copiarli in jasmine-starter / lib. Ora dobbiamo aprire il nostro SpecRunner.html file e regolare il

Si noti che abbiamo due reporter per i nostri test: un reporter HTML e un reporter della console. Questo significa SpecRunner.html e i suoi test possono essere eseguiti sia nel browser che nella console. È utile. Sfortunatamente, dobbiamo averlo console_reporter variabile perché è utilizzata all'interno del file CoffeeScript che stiamo per eseguire.

Quindi, come facciamo realmente a eseguire questi test sulla console? Supponendo che tu sia nel jasmine-starter cartella sul terminale, ecco il comando:

phantomjs lib / run \ _jasmine \ _test.coffee ./SpecRunner.html

Stiamo eseguendo il eseguire \ _jasmine \ _test.coffee script con PhantomJS e passando il nostro SpecRunner.html file come parametro. Dovresti vedere qualcosa di simile a questo:

Naturalmente, se un test fallisce, vedrai qualcosa di simile al seguente:

Se pensi di usarlo spesso, potrebbe essere una buona idea spostarti eseguire \ _jasmine \ _test.coffee in un'altra posizione (come ~ / Bin / run \ _jasmine \ _test.coffee) e creare un alias terminale per l'intero comando. Ecco come lo faresti in una shell Bash:

alias phantom-jasmine = "phantomjs /path/to/run\_jasmine\_test.coffee"

Basta buttarlo nella tua .bashrc o .bash_profile file. Ora puoi solo eseguire:

fantasma-gelsomino SpecRunner.html

Ora i tuoi test Jasmine funzionano bene sul terminale tramite PhantomJS. Puoi vedere il codice finale nel gelsomino-totale cartella nel download.


PhantomJS e Mocha

Per fortuna, è molto più facile integrare Mocha e PhantomJS con mocha-phantomjs. È semplicissimo da installare se hai installato NPM (che dovresti):

npm install -g mocha-phantomjs

Questo comando installa a moka phantomjs binario che useremo per eseguire i nostri test.

In un precedente tutorial, ti ho mostrato come usare Mocha nel terminale, ma farai le cose in modo diverso quando lo utilizzerai per testare il codice DOM. Come con Jasmine, inizieremo con un reporter di test HTML che può essere eseguito nel browser. La bellezza di questo è che saremo in grado di eseguire lo stesso file sul terminale per i risultati dei test della console con PhantomJS; proprio come potremmo fare con Jasmine.

Quindi, costruiamo un progetto semplice. Crea una directory di progetto e spostati in essa. Inizieremo con a package.json file:

"nome": "progetto", "versione": "0.0.1", "devDependencies": "mocha": "*", "chai": "*"

Mocha è il framework di test e useremo Chai come libreria di asserzioni. Installiamo questi eseguendo NPM.

Chiameremo il nostro file di test test / tests.js, e qui ci sono i suoi test:

descrivere ("DOM Tests", function () var el = document.createElement ("div"); el.id = "myDiv"; el.innerHTML = "Ciao!"; el.style.background = "#ccc "; document.body.appendChild (el); var myEl = document.getElementById ('myDiv'); it (" è nel DOM ", function () expect (myEl) .to.not.equal (null); ); it ("è un figlio del corpo", function () expect (myEl.parentElement) .to.equal (document.body);); it ("ha il testo giusto", function ()  expect (myEl.innerHTML) .to.equal ("Ciao!");); it ("ha lo sfondo giusto", function () expect (myEl.style.background) .to.equal ("rgb ( 204, 204, 204) ");););

Sono molto simili ai test di Jasmine, ma la sintassi dell'asserzione di Chai è un po 'diversa (quindi non copiare i tuoi test di Jasmine).

L'ultimo pezzo del puzzle è il TestRunner.html file:

   test     

Ci sono diversi fattori importanti qui. Innanzitutto, nota che questo è abbastanza completo da essere eseguito in un browser; abbiamo il CSS e JavaScript dai moduli del nodo che abbiamo installato. Quindi, nota il tag script inline. Determina se PhantomJS è caricato e, in tal caso, esegue la funzionalità PhantomJS. In caso contrario, si attacca con la funzionalità Mocha raw. Puoi provare questo nel browser e vederlo funzionare.

Per eseguirlo nella console, esegui semplicemente questo:

mocha-phantomjs TestRunner.html

Ecco! Ora i test vengono eseguiti nella console, ed è tutto grazie a PhantomJS.


PhantomJS e Yeoman

Scommetto che non sapevi che il popolare Yeoman usa PhantomJS nella sua procedura di test, ed è sostanzialmente inesistente. Diamo un'occhiata ad un rapido esempio. Immagino che tu abbia Yeoman tutto pronto.

Crea una nuova directory di progetto, corri yeoman init al suo interno e rispondi "No" a tutte le opzioni. Apri il test / index.html file, e troverai un tag script vicino in fondo con un commento che ti dice di sostituirlo con le tue specifiche. Ignora completamente quel buon consiglio e mettilo dentro esso bloccare:

var el = document.createElement ("div"); si aspettano (el.tagName) .to.equal ( "DIV");

Adesso corri test degli yeoman, e vedrai che il test funziona bene. Ora aperto test / index.html file nel browser. Funziona! Perfezionare!

Certo, c'è molto di più che puoi fare con Yeoman, quindi dai un'occhiata alla documentazione di più.


Conclusione

Usa le librerie che estendono PhantomJS per semplificare i tuoi test.

Se stai usando PhantomJS da solo, non c'è alcun motivo per conoscere PhantomJS stesso; puoi semplicemente sapere che esiste e utilizzare le librerie che estendono PhantomJS per semplificare i test.

Spero che questo tutorial ti abbia incoraggiato a esaminare PhantomJS. Consiglio di iniziare con i file di esempio e la documentazione offerta da PhantomJS; apriranno davvero gli occhi su ciò che puoi fare con PhantomJS - tutto dall'automazione delle pagine allo sniffing della rete.

Così, può pensi a un progetto che PhantomJS migliorerebbe? Ne sentiamo parlare nei commenti!