Tips for Making CasperJS Tests More Reliable

Ghost Inspector currently uses CasperJS under the hood — a powerful open source navigation scripting & testing utility. Over the past 6 months we’ve learned a ton about what it takes to make CasperJS tests as reliable as possible.

Because Ghost Inspector doesn’t specifically know anything about the websites we’re testing, we’ve added lots of logic to account for delays, anomalies and other “gotchas” that may popup in our users’ tests. For instance, maybe there’s a slow AJAX call somewhere along the way that takes a couple of seconds to finish. We wanted to be able to handle this right off the bat, without the user having to specify a manual delay in their test. In striving for this goal, we’ve developed a number of strategies and wanted to share a couple of them so that you can leverage them in your own CasperJS tests.

1. Precede all your interactions with waitForSelector().

Casper’s super useful waitForSelector() function tells your test to wait for a specific element to show up before interacting with it. For instance, if you have a button identified as #btn-submit that you want to click, you can do waitForSelector('#btn-submit') before your click('#btn-submit') call. This will ensure that the element is present before the interaction is attempted. While this does lead to more verbose code, it’s a good idea to apply this logic everywhere in your test, just in case.

2. Consider a short, manual delay between each of your steps.

This may seem unnecessary, but sometimes actions like filling in a form can trigger JavaScript validation code on the page, for instance. We’ve found that it can be helpful to give the browser a short period between each step to process what just happened — especially when your website is using JavaScript-heavy frameworks like AngularJS, which need time to bind their actions. By short, we mean something in the 250ms range. You can do this by simply running wait(250) between each step. See what works for you.

3. Take advantage of waitForResource() to track AJAX requests.

Dealing with AJAX requests in your tests can be tricky. Sometimes it’s easiest just to be lazy and add a manual wait() call to make sure the request finishes — but that can be slow and unreliable. If you really want to get ambitious, you can setup a function for casper.options.onResourceRequested that watches AJAX requests, then uses waitForResource() to wait for their response.

Update 06/08/2015

After a couple requests in the comments, I’ve added some sample code to go along with this suggestion. Here’s how you can implement AJAX waiting with CasperJS:

// create list of AJAX urls to track
ajaxUrls = ['/api/results/create.json', '/api/results/list.json'];

// add AJAX waiting logic to onResourceRequested
casper.options.onResourceRequested = function (casper, requestData){
    // loop through our AJAX urls
    ajaxUrls.foreach(function(ajaxUrl){
        // does this request match an AJAX url
        if(requestData.url.indexOf(ajaxUrl) !== -1){
            // it matches, so we'll wait for it to return (with 10s timeout)
            console.log("Waiting for AJAX request: " + requestData.url);
            casper.waitForResource(requestData.url, function(){
                console.log("AJAX request returned: " + requestData.url);
            }, function(){
                console.log("AJAX request didn't return after wait period: " + requestData.url)
            }, 10000);
        }
    });
}

Everyone’s test scenarios are different, so your milage may vary with each of these — but we hope you’re able to get some use out of them!

Justin Klemm

Author: Justin Klemm

Justin is the founder and tech lead at Ghost Inspector. He's a seasoned developer with a passion for innovation. When he's not tinkering with the latest web frameworks, Justin enjoys world traveling, good eats and lots of outdoor activity.

Web | Twitter | Google+