PhantomJS for client side testing
Please note that PhantomJS has been suspended, so this article is only retained out of historical interest.
As web-based projects do more on the client side, conventional server-side performance testing is not able to give you all the performance story. I have, therefore, started looking around for tools which would give more insight into that purely client-side performance.
A Test Application
I needed a client side application to start looking out and brought an old application I had written in the early days of the iPhone out of retirement. It’s a simple set of RGB sliders, which allow you to independently move three sliders and it displays the resulting colour combination, together with its hex code. To make it work a bit harder, it also changes the colour of the red, green and blue sliders as you move them.
Since it was designed for a phone, it doesn’t look too good in a browser. Here’s the screenshot from my phone instead.
Enter PhantomJS
According to its homepage, PhantomJS is a headless WebKit scriptable with a
JavaScript API. What that means is we can write scripts which interact with a
website as if they were a web browser, but unlike older scripted browser agents
(like Perl’s WWW::Mechanize
) they can also interact with the Javascript on the
web pages to execute client side code.
There are other tools in similar spaces, Selenium and ZombieJS spring to mind, but I decided to start looking at PhantomJS because it seems to have a smaller barrier to getting started than Selenium and is more active than ZombieJS. On the other hand, PhantomJS limits you to WebKit, so if you want to test compliance across browsers you need Selenium.
I installed PhantomJS using homebrew
and was up and running in minutes. I
followed a quickstart tutorial and had my first working script very quickly.
My PhantomJS Script
Since PhantomJS is Javascript-based it helps if you understand Javascript code, however since a lot of it is library calls, it is fairly easy to follow anyway.
My first script did two things — generated some screen shots of my application and displayed timings for those activities. To make it interesting, it also moved the sliders during those activities. Just doing these things makes PhantomJS immediately useful — being able to screenshot a web application in a few lines of code is a trick worth having up your sleeve.
Here is my first script …
The first line creates my headless browser and the next two lines set up the size of that browser. I’m trying to mimic an iPhone, so I set the viewport dimensions accordingly. Because I am trying to mimic a more recent iPhone, I also set the zoom to 2 to mimic its higher resolution.
I then grab the current time (in a variable t
) so I can display some timings
as I go.
Next we open our URL (the same one as I mentioned earlier). We use the open()
method on our headless browser for this. It takes two parameters — the page we
want to open and a closure to handle any actions we want to take after the page
has opened.
Once the page has opened, we subtract our time stored earlier from our current
time, to see how long the page load has taken. We then write out a message
(using the log()
function on a console
object, which PhantomJS sets up
automatically for us).
Once we’ve done that, we save a screenshot of what the web page looks like,
using the render()
method on our headless browser.
Now let’s interact with our Javascript code a little. We now send three events to our headless browser – a mousedown, a mousemove and a mouseup. This lets us drag one of our sliders. We need to supply the x and y coordinates that we want these events to happen on (they are measured from top left of the browser). I measured these using a simple image viewer, to get the right values.
We then display the timing for that activity and save a screenshot. Then we move another slider and do the same again.
Running our Script
It is very easy to run our script, using the phantomjs
command and passing
our script as the parameter.
You can see the expected output from the script, a message showing how long the page load took and two further messages with timings for the slider movements.
We also have three screenshots.
;
After the first slider is moved.
;
After the second slider is moved.
;
Summary
That is a brief overview of what PhantomJS can do without much effort. It has encouraged me to explore it a little bit more.