Sunday, May 22, 2011

PhantomJS and QUnit Hello World

I'm starting to develop a lot of meaty javascript and I've finally reached my snapping point for endlessly clicking refresh in a browser. My current project makes heavy usage of SQLite on the client-side, so I needed something fairly sophisticated for running the tests. Enter PhantomJS, a headless WebKit browser. My project is also completely in JQuery, so QUnit seemed like a good fit as it's the testing framework used for JQuery itself.

Installing PhantomJS


The suggested install steps worked great for me. First, get the source:
git clone git://github.com/ariya/phantomjs.git

The Qt build tools must also be installed, which was a snap on OSX. Download the build tools from http://qt.nokia.com/. Once installed simply run:
qmake -spec macx-g++ && make

And then add phantomjs/bin/phantomjs.app/Contents/MacOS/phantomjs to your path.

Installing QUnit


Nothing more than getting the source:
git clone http://github.com/jquery/qunit

Now just copy the qunit directory to your web directory. I then added a very simple qunit test directly in an HTML file and then opened it in my browser:
<link rel="stylesheet" href="qunit/qunit.css">
<script src="qunit/qunit.js"></script>
<script>
test("hello", function() {
ok(true, "world");
});
</script>
<h1 id="qunit-header">QUnit Hello World</h1>
<h2 id="qunit-banner"></h2>
<ol id="qunit-tests"></ol>


Headless Hello World test


Now that phantomjs and qunit are both installed and working it's time to mix the two together. I was in the process of writing a simple test runner, but then I came across https://gist.github.com/796548, which did exactly what I wanted. After downloading that running a headless test was as simple as:
phantomjs testrunner.js file://`pwd`/index.html

The point of all of this was/is to develop not only unit tests, but also full integration tests using SQLite in the browser. Details on the full integration tests to come in a later post.

2 comments:

  1. Awesome! I'm trying to get it working right now. I'm so excited to automate our qunit tests in our build loop.

    One question, I get an error when I run the script:


    agrande-mbp:qunit agrande$ phantomjs testrunner.js file://`pwd`/topsecretproject/index.html
    undefined:1 TypeError: Result of expression 'phantom.state' [undefined] is not an object.

    Any ideas why phantom.state is undefined?

    ReplyDelete
  2. @alex, it looks like my example was using PhantomJS 1.1. Once I updated to 1.2 using git (from the build instructions at http://code.google.com/p/phantomjs/wiki/BuildInstructions) I experienced the same problem as you. So, it looks like the testrunner.js I was using won't work for 1.2. However, phantomjs now includes a qunit testrunner in the source. Look in the examples directory for a "run-qunit.js" file. You're command should now be something like:

    phantomjs <path to phantomjs source>/examples/run-qunit.js file://`pwd`/topsecretproject/index.html

    Good luck!

    ReplyDelete