In our last post we have seen how to install CasperJS and how to make a very simple script. In this post we will make more interesting stuff.

In this tutorial we will see how to catch any error in our web page, whether it be the lack of an image or script or an error in javascript code.

So, lets start forcing these errors. Go to your _layout.cshtml page (or other page if you are not using ASP.NET MVC) and add this line to try to load a non existing script.

<script type="text/javascript" src="js/fake.js"></script>

In the same page, find where the logo link is created

<p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>

and change it for a non existing image, like this:

<a href="http://localhost:8000">
    <img src="~/Content/Images/logo.png"></img>
</a>

Now, go to the site.css file, and add this line to .body

background: url("../Images/noExists.png") no-repeat;

And finally, create a script in Scripts folder with this content and name it error.js

function throwError() {
    throw new Error();
}

throwError();

And add it at the end of your _layout.cshtml page

<script src="~/Scripts/error.js"></script>

If we load the page and take a look at the network tab of the developer tools we could see the errors on resource loading.

[caption id="attachment_51" align="alignnone" width="1239"]error loading resourcees error loading resourcees[/caption]

And taking a look at the errors tab, we could see more errors

[caption id="attachment_52" align="alignnone" width="669"]error loading resources error loading resources[/caption]

So, let's try to catch these errors.

Put this code between the casper.start call and the casper.run call.

casper.start('http://localhost:8000/', function () {
    if (this.resourceExists('fake.js')) {
        this.echo('fake.js is downloaded');
    } else {
        this.echo('fake.js is not downloaded');
    }

    if (this.resourceExists('error.js')) {
        this.echo('error.js is downloaded');
    } else {
        this.echo('error.js is not downloaded');
    }
});

With this code we are asking CasperJS whether fake.js and error.js are downloaded. As a result we should have this output:

[caption id="attachment_56" align="alignnone" width="675"]result result[/caption]

That's great! Error.js exists in our project but fake.js don't. So the result is the expected.

Could we do the same with the images? Yes, of course. Replace the previous code with this one:

casper.start('http://localhost:8000/', function () {
    if (this.resourceExists('logo.png')) {
        this.echo('logo.js is downloaded');
    } else {
        this.echo('logo.js is not downloaded');
    }
});

And we should have this output:

[caption id="attachment_57" align="alignnone" width="676"]result result[/caption]

Ok, that's great but it's not reasonable to have all the resources in our web hardcoded in the script. Let's try to generalize a little bit more. Let's start with the scripts:

var scriptsArray = [];

function getScripts() {
    var scripts = document.querySelectorAll('script[src]');
    return Array.prototype.map.call(scripts, function(e) {
        return e.getAttribute('src');
    });
};

casper.start('http://localhost:8000/', function () {
    scriptsArray = this.evaluate(getScripts);
    var self = this;
    scriptsArray.forEach(function(item) {
        if (self.resourceExists(item)) {
            self.echo(item + ' loaded');
        } else {
            self.echo(item + ' not loaded', 'ERROR');
        }
    });
});

In this script we are retrieving all the page's scripts using a css selector. To do this we have to use the evaluate function. With the array of scripts we could call the resourceExists function to know whether the resource is loaded or not.

Executing the script we should have this result:

[caption id="attachment_58" align="alignnone" width="675"]result result[/caption]

And yes, we could do the same for the images, changing the css selector a little bit:

var imagesArray = [];

function getImages() {
    var scripts = document.querySelectorAll('img[src]');
    return Array.prototype.map.call(scripts, function (e) {
        return e.getAttribute('src');
    });
};

casper.start('http://localhost:8000/', function () {
    imagesArray = this.evaluate(getImages);
    var self = this;
    imagesArray.forEach(function (item) {
        if (self.resourceExists(item)) {
            self.echo(item + ' loaded');
        } else {
            var message = item + ' not loaded';
            self.echo(message, 'ERROR');
        }
    });
});

And the output:

[caption id="attachment_59" align="alignnone" width="675"]result result[/caption]

Could be a good idea to take a snapshot if an image is not loaded. We could do this using the capture function:

casper.start('http://localhost:8000/', function () {
    imagesArray = this.evaluate(getImages);
    var self = this;
    var isThereAnError = false;
    imagesArray.forEach(function (item) {
        if (self.resourceExists(item)) {
            self.echo(item + ' loaded');
        } else {
            var message = item + ' not loaded';
            self.echo(message, 'ERROR');
            self.isThereAnError = true;
        }
    });

    if (this.isThereAnError == true) {
        casper.capture('noimages.png');
    }
});

The output will be the same as before, but if you take a look at the script folder you will see that now there is an image in it:

[caption id="attachment_61" align="alignnone" width="826"]no images no images[/caption]

And if you open the image, you will see the web page rendered.

[caption id="attachment_62" align="alignnone" width="1024"]page rendered page rendered[/caption]

But we have a problem. We don't have any notices about the image set in body's background that doesn't exist. We have to try another approach to catch this error. It would be great to catch any 404 error on resources loading, and CasperJS allows us to do.

Change the previous function by this one:

casper.on("resource.received", function(request) {
    if (request.status === 404) {
        this.echo('Resource Not Found:' + request.url);
    }
});

casper.start('http://localhost:8000/', function () {});

Now, we are subscribing to the resource.received event, and looking at the status code we could know whether the resource is loaded or not.

If we take a look at the output we could see that an error is shown for the image inside the css too.

[caption id="attachment_63" align="alignnone" width="675"]catching 404 errors catching 404 errors[/caption]

 

Ok, now we have a generic way to be aware of errors when loading resources. Now we need to know when a javascript error happens. To do that we are going to use the events too, but now we are going to subscribe to page.error event:

casper.on("page.error", function (msg, trace) {
    this.echo("Error:    " + msg, "ERROR");
    this.echo("file:     " + trace[0].file, "WARNING");
    this.echo("line:     " + trace[0].line, "WARNING");
    this.echo("function: " + trace[0]["function"], "WARNING");
});

And we obtain as a result

[caption id="attachment_64" align="alignnone" width="675"]on error on error[/caption]

So, we have a generic way to obtain the errors loading resources or executing javascript of our web page. In upcoming tutorials we will explore more capabilities of CasperJs.

See you soon!

Today we will start a serie of tutorials about testing websites using CasperJS. We will cover installation and basic error detection, integration with a Team Foundation Server build and executing tests.

What is CasperJS?

In words of its creators, CasperJS is an open source navigation scripting & testing utility written in Javascript and based on PhantomJS — the scriptable headless WebKit engine. It eases the process of defining a full navigation scenario and provides useful high-level functions, methods & syntactic sugar for doing common tasks.

Installation

First of all we have to download the latest version of PhantomJS and extract the contact where you want. After that it's recommended to add this path to your PATH environment variable.

Now you can download the tag 1.0.2 of CasperJS repository on GitHub. You can clone the repository and checkout this tag:

$ git clone git://github.com/n1k0/casperjs.git
$ cd casperjs
$ git checkout tags/1.0.2

or you can download directly from here.

As before, it's recommended to add the path where you have downloaded CasperJS to your PATH environment variable. But don't add the base path, add the batchbin folder.

First steps

To test CasperJS we will use the web site created by the MVC internet application template of Visual Studio 2012. If you are not a .Net developer, please create a simple website with your prefered technology, and skip this step.

For .Net developers, open your VS2012 in administrator mode and create a new project with the MVC4 application project type

[caption id="attachment_32" align="alignnone" width="300"]Project template Project template[/caption]

And now chose the internet application template

ProjectCreation2

 

In order to facilitate our job, we will create a new web site on IIS and link it to our brand-new project. So please, open IIS manager and create a new website

[caption id="attachment_35" align="alignnone" width="599"]Web site creation Web site creation[/caption]

And now open the properties window of the web site application project in VS2012 and associate the project to the new web site we've just created

[caption id="attachment_36" align="alignnone" width="1199"]project properties project properties[/caption]

Now, add a folder under the Scripts folder and create a new JavaScript file called testCasperJS.js.

Working with CasperJS

All the scripts start with a call to 'create' method. The simplest way to do it is this:

var casper = require('casper').create();

You can pass a javascript settings object to this method with several parameters. For example, we could set the viewport size:

var casper = require('casper').create({
    viewportSize: {width: 1024, height: 768}
});

The next function we need to call is 'start'. This call could be without parameters or we could pass an Url and the function that will be called after the page downloading.

casper.start('http://localhost:8000/', function () {
    this.echo('page downloaded: ' + this.getCurrentUrl());
});

Now, we only need one more code block to end our first CasperJS script

casper.run(function () {
    this.echo("Done.").exit();
});

With this code, we are indicating to CasperJS that we want to run our script and that, when it finishes we  want to write 'Done' in the console and exit CasperJS.

Right now, we could save our script, open a Command Prompt, go where the script is located and write

casperjs testCasperJs.js

And we will see the result of our script

[caption id="attachment_42" align="alignnone" width="677"]script result script result[/caption]

Conclusions

In this post we have seen how to install CasperJS and how to make a very simple script. In the next posts of this series, we will see more operations to use and how to integrate all these scripts in a build for our Team Foundation Server.

See you soon!

 

 

 

 

 

Last week I attended to Agile Dev Practices, a brand-new conference done in Postdam, organized by Diaz Hilterscheid, the people behind the renowned Agile Testing Days. It was my third international conference (the first outside Spain) and the first one I have gone as a speaker.

I had the good fortune to assist to Carlos Blé tutorial about “Practical BDD for RIAs with JavaScript”. It was a great tutorial, more suitable to do in two days (or at least, one and a half) but equally great. I got useful insights and a lot of stuff to study.

That Monday at night, all the speakers went to the speakers dinner. I shared table with an amazing group of people like Jan Ehrhardt, Daniel Maslyn, Marko Taipale and Gáspár Nagy. A very funny and instructive dinner.

The conference itself went well. Maybe a little bit less people than expected, probably because of the coincidence with QCon conference and because of it was the first edition of the conference.

Some of the talks and the keynotes were really great, but the best, as always, was the possibility of knowing great professionals with tons of experience and be able to talk with them.

My session was on Wednesday. It consisted in three exercises to study the people’s behavior in a retrospective, ending with some advises to try to create a good environment in a retrospective. Here you have the extended version of the slides.

I encourage all of you to go to as many conferences outside your country you can. I know it could be a big expense, but sometimes a flight to a foreign country is cheaper than an internal one, and the hotels all expensive everywhere. But you will open your mind, meet great professionals and learn lots of things.

For my part, I take as homework to study Behavior Driven Development and Specflow in depth.