CasperJS for User Experience and Regression Testing

By Silviu, on 2016-01-07

Available as open source, CasperJS is a great scripting tool that allows automated unit and regression testing for web applications.

Overview

With almost every change, big or small, to a web application's front-end or back-end code, we carry that nagging, butterfly effect feeling at the back of our minds: "Have we broken anything remotely connected with our latest work ?"

While unit testing is a good first line of defence, there is another angle to prevent unpleasant surprises, and solve those kind of anxieties: regression testing by simulating user navigation scenarios.

CasperJS is such a tool, and it makes use of either PhantomJS or SlimerJS as scripting engines, so you can use plain Javascript to write the test cases. It represents a viable alternatives to dedicated tools, such as Selenium.

The purpose of this article is to get you started with installation of CasperJS on Linux and Windows, and to offer a few implementation tips, as well as how to package and organize tests to make them accessible from integration tools.

Installing CasperJS

Assumptions

Since Casper is basically a giant collection of Javascript modules, it relies on one of the two scripted engines mentioned above.

This tutorial will install CasperJS and PhantomJS inside an ArchLinux Docker container. I prefer this approach because it is more secure for your host system (no worries about precompiled binaries, such as PhantomJS), and also because it creates a functional separation for your regression testing tools.

You can, of course, install Casper and Phantom directly inside your main OS, and skip this section altogether.

For the Docker approach, we will assume that you already have a recent (1.12 and later) version of Docker, and that CasperJS will be installed in the user's home folder, in the ~/tools/casperjs/docker-volume directory, which will be mapped to a docker container inner path.

Setting Up the Docker Image

We are going to slightly customize an existing command-line-ready ArchLinux image from DockerHub:
https://hub.docker.com/r/oddlid/arch-cli-minimal/

Create a file named Dockerfile inside ~/tools/casperjs/ with the following contents:

FROM oddlid/arch-cli-minimal:latest

# Install packages for both ease of use and 
# structurally needed for PhantomJS (fontconfig)
RUN pacman -S --noconfirm --needed fontconfig nodejs npm
RUN pacman -S --noconfirm --needed nano htop wget

# Ensure the system locale is English
RUN locale-gen en_US.UTF-8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'

# Set up basic aliases for convenience
RUN echo "alias ll='ls -alF'" >> ~/.bashrc
RUN echo "alias la='ls -A'" >> ~/.bashrc
RUN echo "alias l='ls -CF'" >> ~/.bashrc

You can now install the image on your computer:

docker build -t caspertest/archlinux .

We now have a docker image, let's create a convenient script file, at:
~/tools/casperjs/start-casper-arch-docker.sh
that we can use to start the container and log us inside a Casper-ready ArchLinux session whenever we wish to run some CasperJS scripts:

#!/usr/bin/env bash

HOST_PATH="/home/${USER}/tools/casperjs/docker-volume"
CONTAINER_PATH="/casperjs"

# Start the Arch Linux docker container for Casper and enter the interactive mode using bash
docker run -it --name casperjs_instance -v ${HOST_PATH}:${CONTAINER_PATH} --rm caspertest/archlinux /bin/bash

Installing the Containerized Tools

Run the script and you should be prompted with the typical ArchLinux hashtag prompt, with the /casperjs location pointing to our host's /tools/casperjs/docker-volume as per the docker run mapping.

Change directory to /casperjs and create another (inner) convenience shell script, /casperjs/run-casper.sh as follows:

#!/usr/bin/env bash

export PHANTOMJS_EXECUTABLE=/casperjs/phantomjs/bin/phantomjs

# Add PhantomJS to PATH if not there already
if [[ ":$PATH:" != *":/casperjs/phantomjs/bin:"* ]]; then export PATH=${PATH}:/casperjs/phantomjs/bin; fi

/casperjs/node_modules/casperjs/bin/casperjs $@

Now, let's install PhantomJS inside the /casperjs/phantomjs subdirectory (for the most available version, see the download page):

# wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
# tar -xvjf phantomjs-2.1.1-linux-x86_64.tar.bz2
# rm phantomjs-2.1.1-linux-x86_64.tar.bz2 && mv phantomjs-2.1.1-linux-x86_64/ phantomjs/

Finally, install CasperJS. Recently things have gotten much simpler, with an npm installer available:

# npm install casperjs

We're now ready for a self-test, and we are going to use the run-casper.sh script, that makes sure to make the PhantomJS engine whereabouts known to Casper, as well as to pass on all the command line arguments:

# ./run-casper.sh selftest

Ok, all tests hopefully passed, let's run the statutory "Hello World" test. Create a new file, named hello-test.js, in the very same /casperjs directory as the run-casper.sh script, with the following content (taken from the CasperJS quickstart page):

// hello-test.js
casper.test.begin("Hello, Test!", 1, function(test) {
  test.assert(true);
  test.done();
});

Running it should give us the final confirmation that we're in business:

# ./run-casper.sh test hello-test.js
Test file: hello-test.js                                                        
# Hello, Test!
PASS Subject is strictly true
PASS Hello, Test! (1 test)
PASS 1 test executed in 0.021s, 1 passed, 0 failed, 0 dubious, 0 skipped.