JavaScript testen met PhantomJS

Ik denk niet dat ik je moet overtuigen dat het testen van je JavaScript-code een goed idee is. Maar het kan soms vervelend zijn om JavaScript-code te testen waarvoor een DOM vereist is. Dit betekent dat je je code in de browser moet testen en de terminal niet kunt gebruiken, toch? Fout, eigenlijk: ga naar PhantomJS.


Wat is PhantomJS precies? Nou, hier is een blurb van de PhantomJS-website:

PhantomJS is een headless WebKit met JavaScript API.

Zoals u weet, is Webkit de layout-engine die Chrome, Safari en enkele andere niche-browsers gebruiken. Dus PhantomJS is een browser, maar een browser zonder kop. Dit betekent dat de weergegeven webpagina's nooit daadwerkelijk worden weergegeven. Dit klinkt misschien raar voor je; dus je kunt het beschouwen als een programmeerbare browser voor de terminal. We zullen in een minuut een eenvoudig voorbeeld bekijken, maar we moeten eerst PhantomJS installeren.


Installeren van PhantomJS

Het installeren van PhantomJS is eigenlijk vrij eenvoudig: het is slechts één binair bestand dat u downloadt en in uw terminalpad houdt. Op de PhantomJS-downloadpagina kiest u uw besturingssysteem en downloadt u het juiste pakket. Verplaats vervolgens het binaire bestand van het gedownloade pakket naar een map binnen uw terminalpad (ik houd er van dit soort dingen in te stoppen ~ / Bin).

Als je Mac OS X gebruikt, is er een eenvoudigere manier om PhantomJS te installeren (en dit is eigenlijk de methode die ik heb gebruikt). Gebruik gewoon Homebrew, zoals dit:

brouw update && brouw phantomjs installeren

U moet PhantomJS nu hebben geïnstalleerd. U kunt uw installatie controleren door dit uit te voeren:

phantomjs --version

Ik zie 1.7.0; u?


Een klein voorbeeld

Laten we beginnen met een klein voorbeeld.

simple.js
console.log ("we kunnen dingen loggen."); functie toevoegen (a, b) return a + b;  conslole.log ("We kunnen ook reguliere JS uitvoeren:", add (1, 2)); phantom.exit ();

Ga je gang en voer deze code uit door het volgende commando te geven:

phantomjs simple.js

Je zou de uitvoer van de twee moeten zien console.log regels in uw terminalvenster.

Natuurlijk, dit is eenvoudig, maar het is een goed punt: PhantomJS kan JavaScript uitvoeren net als een browser. Dit voorbeeld heeft echter geen PhantomJS-specifieke code ... nou, afgezien van de laatste regel. Dat is een belangrijke regel voor elk PhantomJS-script omdat het script wordt afgesloten. Dit is hier misschien niet logisch, maar vergeet niet dat JavaScript niet altijd lineair uitvoert. U wilt bijvoorbeeld de Uitgang() oproep in een callback-functie.

Laten we een meer gecompliceerd voorbeeld bekijken.


Pagina's laden

Met de PhantomJS API kunnen we elke URL laden en met de pagina werken vanuit twee perspectieven:

  • als JavaScript op de pagina.
  • als een gebruiker die naar de pagina kijkt.

Laten we beginnen met het laden van een pagina. Maak een nieuw scriptbestand en voeg de volgende code toe:

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

We beginnen met het laden van PhantomJS ' webpagina module en het maken van een webpagina-object. We noemen dan de Open methode, doorgeven van een URL en een callback-functie; het is binnen deze callback-functie die we kunnen communiceren met de eigenlijke pagina. In het bovenstaande voorbeeld loggen we gewoon de status van het verzoek in, verstrekt door de parameter van de callback-functie. Als u dit script uitvoert (met phantomjs script.js), moet u 'succes' laten afdrukken in de terminal.

Maar laten we dit interessanter maken door een pagina te laden en er JavaScript op uit te voeren. We beginnen met de bovenstaande code, maar we bellen dan naar page.evaluate:

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

PhantomJS is een browser, maar een browser zonder kop.

De functie waar we doorheen gaan page.evaluate wordt als JavaScript uitgevoerd op de geladen webpagina. In dit geval vinden we alle elementen met de post klasse; dan stellen we de achtergrond van het eerste bericht in op zwart. Ten slotte geven we de document titel. Dit is een leuke functie, die een waarde retourneert van onze schatten terugbellen en toewijzen aan een variabele (in dit geval, titel).

Vervolgens hebben we de clipRect op de pagina; dit zijn de afmetingen voor het screenshot dat we maken met de geven methode. Zoals je kunt zien, hebben we de top en links waarden om het startpunt in te stellen, en we stellen ook een breedte en hoogte. Eindelijk bellen we page.render, het doorgeven van een naam voor het bestand (de titel variabel). Dan eindigen we door te roepen phantom.exit ().

Ga je gang en voer dit script uit, en je zou een afbeelding moeten hebben die er ongeveer zo uitziet:

U kunt beide kanten van de PhantomJS-munt hier zien: we kunnen JavaScript van binnenuit de pagina uitvoeren en ook van buitenaf uitvoeren, op de pagina-instantie zelf.

Dit was leuk, maar niet ongelooflijk nuttig. Laten we ons concentreren op het gebruik van PhantomJS bij het testen van ons DOM-gerelateerde JavaScript.


Testen met PhantomJS

Yeoman gebruikt PhantomJS in zijn testprocedure en het is vrijwel naadloos.

Voor veel JavaScript-code kunt u testen zonder een DOM nodig te hebben, maar er zijn momenten waarop uw tests met HTML-elementen moeten werken. Als je net als ik bent en er de voorkeur aan geeft om tests uit te voeren op de opdrachtregel, dan komt hier PhantomJS om de hoek kijken.

Natuurlijk is PhantomJS geen testbibliotheek, maar veel van de andere populaire testbibliotheken kunnen bovenop PhantomJS worden uitgevoerd. Zoals je kunt zien op de PhantomJS wikipagina over headless testen, zijn PhantomJS testlopers beschikbaar voor vrijwel elke testbibliotheek die je zou willen gebruiken. Laten we eens kijken naar het gebruik van PhantomJS met Jasmine en Mocha.

Ten eerste Jasmine en een disclaimer: er is op dit moment geen goede PhantomJS-runner voor Jasmine. Als u Windows en Visual Studio gebruikt, moet u Chutzpah bekijken en ontwikkelaars van Rails moeten bewakings-jasmijn proberen. Maar anders dan dat, is ondersteuning van Jasmine + PhantomJS schaars.

Om deze reden raad ik aan om Mocha te gebruiken voor DOM-gerelateerde tests.

ECHTER.

Het is mogelijk dat je al een project hebt met Jasmine en het wilt gebruiken met PhantomJS. Eén project, phantom-jasmine, neemt een beetje werk in beslag, maar het zou de slag moeten slaan.

Laten we beginnen met een set JasmineJS-tests. Download de code voor deze tutorial (link bovenaan) en bekijk de jasmijn-starter map. Je zult zien dat we een single hebben tests.js bestand dat een DOM-element maakt, een paar eigenschappen instelt en dit aan de hoofdtekst toevoegt. Vervolgens voeren we een paar Jasmine-tests uit om te zorgen dat dit proces inderdaad goed werkt. Dit is de inhoud van dat bestand:

tests.js
beschrijven ("DOM-tests", functie () var el = document.createElement ("div"); el.id = "myDiv"; el.innerHTML = "Hallo daar!"; el.style.background = "#ccc "; document.body.appendChild (el); var myEl = document.getElementById ('myDiv'); it (" is in de DOM ", function () expect (myEl) .not.toBeNull ();); it ("is een kind van het lichaam", functie () verwachten (myEl.parentElement) .toBe (document.body);); it ("heeft de juiste tekst", functie () verwachten (mijnEl.innerHTML ) .toEqual ("Hallo daar!");); it ("heeft de juiste achtergrond", functie () verwachten (myEl.style.background) .toEqual ("rgb (204, 204, 204)"); ););

De SpecRunner.html bestand is redelijk op voorraad; het enige verschil is dat ik de scripttags in de body heb verplaatst om ervoor te zorgen dat de DOM volledig wordt geladen voordat onze tests worden uitgevoerd. U kunt het bestand openen in een browser en zien dat alle tests goed verlopen.

Laten we dit project overzetten naar PhantomJS. Kop eerst het phantom-jasmijnproject:

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

Dit project is niet zo georganiseerd als het zou kunnen zijn, maar er zijn twee belangrijke onderdelen die je nodig hebt:

  • de PhantomJS runner (waardoor Jasmine een PhantomJS DOM gebruikt).
  • de reportage van de Jasmine-console (die de uitvoer van de console geeft).

Beide bestanden bevinden zich in de lib map; kopieer ze in jasmijn-starter / lib. We moeten nu onze SpecRunner.html bestand en pas het aan

Merk op dat we twee reporters hebben voor onze tests: een HTML-verslaggever en een consoleverslaggever. Dit betekent SpecRunner.html en de tests kunnen zowel in de browser als op de console worden uitgevoerd. Dat is handig. Helaas moeten we dat hebben console_reporter variabele omdat het wordt gebruikt in het CoffeeScript-bestand dat we gaan gebruiken.

Dus, hoe gaan we om met het daadwerkelijk uitvoeren van deze tests op de console? Ervan uitgaande dat je in de jasmijn-starter map op de terminal, hier is de opdracht:

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

We hebben de run \ _jasmine \ _test.coffee script met PhantomJS en passeren onze SpecRunner.html bestand als een parameter. Je zou zoiets als dit moeten zien:

Als een test mislukt, zie je natuurlijk het volgende:

Als u van plan bent dit vaak te gebruiken, kan het een goed idee zijn om te verplaatsen run \ _jasmine \ _test.coffee naar een andere locatie (zoals ~ / Bin / de in werking \ _jasmine \ _test.coffee) en maak een terminalalias voor de hele opdracht. Hier is hoe je dat zou doen in een Bash-shell:

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

Gooi dat gewoon in je .bashrc of .bash_profile het dossier. Nu kun je gewoon rennen:

phantom-jasmine SpecRunner.html

Nu werken uw Jasmine-testen prima via PhantomJS op de terminal. U kunt de definitieve code in de jasmijnvoeten totale map in de download.


PhantomJS en Mocha

Gelukkig is het veel eenvoudiger om Mocha en PhantomJS te integreren met mokka-phantomj's. Het is supereenvoudig om te installeren als u NPM hebt geïnstalleerd (wat u zou moeten doen):

npm install -g mocha-phantomjs

Met deze opdracht installeert u een mokka-phantomjs binair getal dat we gebruiken om onze tests uit te voeren.

In een eerdere zelfstudie heb ik je laten zien hoe je Mocha in de terminal kunt gebruiken, maar je doet het anders als je DOC-code test. Net als bij Jasmine beginnen we met een HTML-testrapportage die in de browser kan worden uitgevoerd. Het mooie hiervan is dat we hetzelfde bestand op de terminal kunnen gebruiken voor de testresultaten van de console met PhantomJS; net zoals we konden met Jasmine.

Laten we dus een eenvoudig project bouwen. Maak een projectdirectory en ga erin. We beginnen met een package.json het dossier:

"naam": "project", "version": "0.0.1", "devDependencies": "mokka": "*", "chai": "*"

Mocha is het testraamwerk en we zullen Chai gebruiken als onze assertiebibliotheek. We installeren deze door NPM uit te voeren.

We zullen ons testbestand bellen test / tests.js, en hier zijn de tests:

beschrijven ("DOM-tests", functie () var el = document.createElement ("div"); el.id = "myDiv"; el.innerHTML = "Hallo daar!"; el.style.background = "#ccc "; document.body.appendChild (el); var myEl = document.getElementById ('myDiv'); it (" is in de DOM ", functie () expect (myEl) .to.not.equal (null); ); it ("is een kind van het lichaam", functie () verwachten (myEl.parentElement) .to.equal (document.body);); it ("heeft de juiste tekst", functie ()  verwachten (myEl.innerHTML) .to.equal ("Hallo daar!");); it ("heeft de juiste achtergrond", function () expect (myEl.style.background) .to.equal ("rgb ( 204, 204, 204) ");););

Ze lijken erg op de Jasmine-tests, maar de Chai-assertiesyntaxis is een beetje anders (dus kopieer niet alleen je Jasmine-tests).

Het laatste stukje van de puzzel is de TestRunner.html het dossier:

   Tests     

Er zijn verschillende belangrijke factoren hier. Merk allereerst op dat dit volledig genoeg is om in een browser te draaien; we hebben de CSS en JavaScript van de knooppuntmodules die we hebben geïnstalleerd. Merk vervolgens de inline script-tag op. Dit bepaalt of PhantomJS is geladen en, zo ja, wordt de PhantomJS-functionaliteit uitgevoerd. Anders blijft het hangen met onbewerkte Mocha-functionaliteit. Je kunt dit uitproberen in de browser en zien hoe het werkt.

Voer het volgende uit om het in de console uit te voeren:

mocha-phantomjs TestRunner.html

Voila! Nu zijn er tests in de console, en het is allemaal dankzij PhantomJS.


PhantomJS en Yeoman

Ik wed dat je niet wist dat de populaire Yeoman PhantomJS gebruikt in zijn testprocedure, en dat het vritually lijkt. Laten we een snel voorbeeld bekijken. Ik neem aan dat je Yeoman alles hebt ingesteld.

Maak een nieuwe projectdirectory, voer uit yeoman init erin en antwoord 'Nee' op alle opties. Open de test / index.html bestand, en u zult een scripttag onderaan vinden met een commentaar dat u vertelt om het te vervangen door uw eigen specificaties. Negeer dat goede advies volledig en plaats dit in de het blok:

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

Nu, ren yeoman test, en je zult zien dat de test goed verloopt. Nu open test / index.html bestand in de browser. Het werkt! Perfect!

Natuurlijk kun je nog veel meer doen met Yeoman, dus bekijk de documentatie voor meer informatie.


Conclusie

Gebruik de bibliotheken die PhantomJS uitbreiden om uw testen eenvoudiger te maken.

Als u PhantomJS alleen gebruikt, is er geen enkele reden om meer te weten te komen over PhantomJS zelf; je kunt gewoon weten dat het bestaat en de bibliotheken die PhantomJS gebruiken gebruiken om het testen eenvoudiger te maken.

Ik hoop dat deze tutorial je heeft aangemoedigd om naar PhantomJS te kijken. Ik raad aan te beginnen met de voorbeeldbestanden en documentatie die PhantomJS aanbiedt; ze zullen je ogen echt openen voor wat je met PhantomJS kunt doen - van pagina-automatisering tot netwerksnuiven.

Zo, kan je denkt aan een project dat PhantomJS zou verbeteren? Laten we erover horen in de reacties!