Suche
Suche Menü

Headless Testing with phantomJS / CasperJS

What was the starting position

For a customer, a website which provides more selective results from apple´s and google´s app stores, i started to write a test suite to check, if the behaviour and reaction of the website on user interaction is as expected.

Familiar with jasmine, jUnit and a little bit with angular testing using protractor the customer decised to use casperJS because casperJS is using phantomJS for headless communication and the customer already uses phantomJS for his website grabbing.

Additionally information can be found at the project pages:
phantomJS
casperJS
slimerJS

Preparation

To start i just needed zu install phantomJS and casperJS with npm globally:

npm install -g phantomjs
npm install -g casperjs

After installation, i get for:
phantomjs --version

1.9.7

And for
casperjs --version

1.1.0-beta3

Additionally i also installed slimerJS which is a scriptable browser for Web developers and provides the same api than phantomJS.

The most exciting thing about slimerjs is, that you can switch from phantomJS to slimerJS by just adding a parameter to the casperjs call.

First Steps with casperJS

CasperJS can be used for both, unit tests and end to end tests (e2e-tests) but, because it is based on phantomJS, its main usage is for e2e-tests.

THe main idea of frameworks like phantomJS and casperJS is, to get an instance of a webpage and get access to parts of the DOM (document object model) via html nodes or css selectors.

To start with casperJS, the project page shows a good example which demonstrates most of the basic principles of casperJS:

 

Executing this script with

casperjs googlelinks.js

generates the following output at the console:

20 links found:
– https://github.com/n1k0/casperjs
– https://github.com/n1k0/casperjs/issues/2
– https://github.com/n1k0/casperjs/tree/master/samples
– https://github.com/n1k0/casperjs/commits/master/
– http://www.facebook.com/people/Casper-Js/100000337260665
– http://www.facebook.com/public/Casper-Js
– http://hashtags.org/tag/CasperJS/
– http://www.zerotohundred.com/newforums/members/casper-js.html
– http://www.yellowpages.com/casper-wy/j-s-enterprises
– http://local.trib.com/casper+wy/j+s+chinese+restaurant.zq.html
– http://www.phantomjs.org/
– http://code.google.com/p/phantomjs/
– http://code.google.com/p/phantomjs/wiki/QuickStart
– http://svay.com/blog/index/post/2011/08/31/Paris-JS-10-%3A-Introduction-%C3%A0-PhantomJS
– https://github.com/ariya/phantomjs
– http://dailyjs.com/2011/01/28/phantoms/
– http://css.dzone.com/articles/phantom-js-alternative
– http://pilvee.com/blog/tag/phantom-js/
– http://ariya.blogspot.com/2011/01/phantomjs-minimalistic-headless-webkit.html
– http://www.readwriteweb.com/hack/2011/03/phantomjs-the-power-of-webkit.php

What is the skeleton of a typical casperJS code?

  1. instance of casper object with
 var casper = require(„casper“).create();
  2. start with calling a website 
casper.start('http://www.google.fr', function() {});
  3. Additional steps with several methods like
    casper.then(function() {});
    capser.thenOpen(‚‘, function() {});
    casper.waitFor('', function() {});
    within the functions tests, parsing of page parts can be done. At our example, the search field will be filled with a text and the query will be started.

  4. the run function is important because it starts the while process.
    casper.run(function() {});

The list of all properties and methods for the casper object can be found at the [api documentation].

Cascading and encapsilating of functions is allowed and often used.

As casperJS is javascript, you need to be aware of the asynchronous behaviour of javascript. With encapsualting all related actions within a .then() call, casperJS takes care of serializing the steps.

 

The command line

casperJS has to be called from the command line.
The basic call for web scraping is
casperjs yourFile.js

For testing you need to add the parameter test:
casperjs test yourTestFile.js

Of course you can select multiple files by concatenating:
casperjs test test1.js test2.js test3.js

Or by using a filter like
casperjs test test*.js

To control your output you can set the log messages with --verbose and the log level with --log-level=[debug|info|waring|error].

To change the engine e.g. from phantomJS (which is standard) to slimerJS you use --engine=[phantomjs|slimerjs].

I for myself found it pretty helpful during development to use slimerJS because you can see live what´s going on at the browser which could be pretty helpful of you manipulate the dom, css or mouse and want to be sure to get the expected result.

With --includes=yourFile.js you can include a file with general information which will be included with every loaded test file.

Using —-pre=xx.js and —-post=yy.js files will be executed before or after each test, e.g. to prepare or clean up elements with which the tests are interacting.

--fail-fast in the end will terminate the test suite as soon as the first test fails.

There are a few more parameters which can be found at the [documentation].

First tests with casperJS

Of course you can do unit tests with casperJS. The [example at the project website] shows the principle.

We now take a look into the e2e-testing with casperJS.

For testing, the basic skeleton of a casperJS file slidely changes a little bit:

 

So we encapsualte the casper web-scraping functions within a call of caspers test object with the method begin()

A complete overview on all test methods can be found at the [api documentation].

Besides simple assert method, there are a lot of specialized methods for testing parts and behaviour of the complete web code like:
– assertElementCount
– assertFieldname
– assertFieldCSS
– AssertSelectorHasText

and so on.

Besides a simple comment function (this.comment()) which can be used for debugging or simple message output, a special echo method is also available:
`casper.echo(„message“, „style“);
`
There are the following styles available:
– ERROR: white text on red background
– INFO: green text
– TRACE: green text
– PARAMETER: cyan text
– COMMENT: yellow text
– WARNING: red text
– GREEN_BAR: white text on green background
– RED_BAR: white text on red background
– INFO_BAR: cyan text
– WARN_BAR: white text on orange background

is using these styles also for its own output so be careful to not get confused 😉

Advanced automated testing with casperJS

I will not try to explain all of the methods of casper and casper.test. The [documentation] is pretty good and helpful, mostly presenting examples for usage.

What really makes it smart is to use casper testing within other javascript code like forEach loops etc.

You have different options on your page and want to perform a test for each of the options? No problem:

The basic approach would be:

  1. create a basic test skeleton
  2. define a module global array at beginning of the file
  3. after starting your test skript with casper.start() interact with your page, read out all the options and save them into the array.
  4. Now perform a yourArray.forEach(function(item, index, yourArray) {}); and perform within your loop the test for each of your options.

Or you want it the other way round:

  1. Define a module global array and save your information into the array, maybe a list of urls.
  2. Now perform again a forEach loop over your array and define your test within this loop for each url with casper.test.begin(url, function....

These are just two simple examples to show, how flexible casperJS is in defining automated tests for websites.

Generell configuration file inclusion

I prefer to have my main configuration parameter and information within an extra file to keep it maintainable etc.

So we now will add a conf.js with the following content:

You can add easily general information which cann than be called within casper scripts by using the casper object.

I also prefer to switch the client console log on and off.

If debugRemoteConsole is set to true, all console.log from the browser client will be printed to local console.log.