article .the-content p {
line-height: 24px;
}

The HootSuite web dashboard is quite front-end heavy. We have a large JavaScript codebase and a lot of it was written using jQuery, with most of the code touching the DOM in some way. Due to the coupling of the code with the DOM, unit testing gets a bit complicated as HTML fixtures will have to be supplied for tests. It’s not impossible, but it’s a bit more work, and experience shows that developers are more likely to write tests when they’re convienent. We’ve adopted to use [CasperJS](http://casperjs.org/) to fill the gaps in our unit test coverage.

I’m not going to cover the basics of CasperJS as the [documentation](http://docs.casperjs.org/en/latest/modules/index.html) is pretty good; I’ll just jump right in to several key things that help us use CasperJS for testing.

#### Routines

There are certain steps which get performed over and over in your system, or steps which help set up testing of a certain area of the application. We’ve bundled these steps into functions which can be called in any test to get the app in a certain state. For example, here’s a routine function for logging into the HootSuite dashboard.


var routine = {};
// define a routine function for login
routine.login = function(email, pass) {
casper.open(url);
casper.waitUntilVisible('form#loginForm', function() {
this.fill('form#loginForm', {
'loginInfo[email]': email,
'loginInfo[password]': pass
}, true);
});
casper.waitForSelector('#dashboard', function() {
this.echo('Logged in', 'COMMENT');
});
};

// then inside my test
casper.then(function() {
routine.login('example@example.com', 'secretpassword');
});
casper.then(function() {
// continue with test
});

#### Teardown

There are times when we need to perform some cleanup after running a test, especially after executing certain routines. For example, we have a routine which adds a Twitter social network to a HootSuite account, but after the test we want to remove the added social network so that it can be added again for another test.

We have an array to store teardown “steps” we have to perform, and we add the steps after performing certain routines.

var teardownSteps = [];

routine.addTwitterSocialNetwork = function(username, password) {
// add the social network...

// add a function to the teardown
teardownSteps.push(function() {
routine.removeSocialNetwork(username);
});
};

The function which process the teardown steps looks something like this.

var doTeardown = function() {
var count = 1,
max = teardownSteps.length;
var fnDoStep = function() {
if (!teardownSteps.length) {
return;
}

var fnToRun = teardownSteps.shift();
casper.then(function() {
this.echo('Do teardown step '+count+' of '+max, 'COMMENT');
count++;
fnToRun.call(casper, null);
});

casper.then(function() {
fnDoStep();
});
};

// do the teardown steps in reverse order
// this is done so that we "undo" our test steps
teardownSteps.reverse();
fnDoStep();
};

We then call the doTeardown() function when the tests are done, or when there is an error.

casper.test.on('fail', function() {
doTeardown();
});

**Note**: this was done before CasperJS 1.1 was released, which now includes a built-in teardown method with [begin()](http://docs.casperjs.org/en/latest/modules/tester.html#begin). We’re moving some of our tests to use this method.

#### Screenshot on fail/error

This should be pretty straight forward, but having a screenshot when tests fail is very useful.


casper.test.on('fail', function() {
casper.capture('screenshots/fail.png');
});

While our current functional testing setup is working well, there are several challenges we want to tackle. These don’t have anything specific to do with CasperJS, but I feel they’re worth mentioning.

#### Test coverage

Unit tests have code coverage which can show how many lines of code has been executed and tested. Since there is nothing like that in functional testing, it’s usually hard to gauge which areas of the code has been covered by tests. Usually this can be mitigated by naming your tests well, but I was considering using [JSDoc](http://usejsdoc.org/) comments to generate a list of user stories that have been tested. We already use JSDoc to generate documentation for our project, so this can be an easy thing to add when writing our tests.

#### Running tests from different authors

When running all the CasperJS tests together, care must be taken to ensure that each test is self-contained and that the appropriate teardown steps be taken so that each test can start from a default state. We’re trying to make sure that tests finish with sufficient cleanup so that shared resources like Social Networks are released and accounts are deleted. Some tests and routine functions also assert to make sure that the current state of the HootSuite dashboard is fresh before starting.

We’re just starting with CasperJS but we’re keeping an eye on how we write tests and if there are any opportunities to make it better. There’s a lot of value in functional testing and it’s a great supplement to unit testing. The challenges I mentioned don’t hinder our usage of CasperJS, and if anyone has experience dealing with those issues or just functional testing in general please leave a comment!

—————–

Javascript pro? Interested in building awesome products with a stellar team? Apply here!