I'm sure most of the people reading this blog have heard of the term "automated testing" before. Automated testing is exactly what it says on the tin, it's a way to test your websites and web applications rigorously and consistently, testing routines can even be built in to your deployment system such as Jenkins or Octopus to ensure any changes you make to a system don't impact any of the other features you've already developed.

Why automate your testing process?

I think the key answer to this question lies with consistency, although human testing is good, automating the process takes away the possibility of human error and ensures a consistent approach is taken everytime.

Lets take for example, a contact form... This is a fairly standard test, we get the driver to fill in a form, submit the form and then check whether an error is returned - doing this over and over again is laborious and could easily be forgotten. By writing a test routine using the language of your choice (in the case of this guide, Javascript) you can run it on every single deployment and force it to fail the deployment should any errors appear.

Getting started

So, the first step before we can do anything is to grab a copy of NodeJS and install it if you haven't already. Grab the installer from the NodeJS website, run it and follow the installation process.

Once you have NodeJS installed we then need to install the Chrome driver, this basically allows your testing routine to control Chrome and do exactly what you tell it to do. Download the latest version and put it in an accessible location, you can download it from the Google APIs website.

You need to then put the location of the driver in your PATH environment variable. In Windows this is found by right clicking Computer -> Properties -> Advanced system settings -> Environment Variables. Add the location of your file to the Path user variable, e.g. c:\Utilities\ChromeDriver.

On Mac to modify your PATH variable open the .profile file from your home directory with your terminal and do the exact same as above. For more info/advice see the article over at Tech Recipes.

Time to get your hands dirty

For demonstration purposes, create a directory inside your local WWW directory called "automation" or something similar. Using CMD on Windows or Terminal on Mac we need to install 2 more things, one of them is installed globally on the machine whereas the other sits within the testing directory.

The first one is Mocha which is a Javascript based testing framework, pretty neat and easy to use. To install it run the following from your command line:

npm -g install mocha

The -g flag tells it to install globally rather than locally.

Once you've installed mocha you then need to CD in to the directory we created earlier "automation" and install the selenium files by running the following:

npm install selenium-webdriver

And that's the setup done! For future reference, all you will need to do is install the selenium files as above, everything else already exists on your machine.

Writing some tests

Time to REALLY get your hands dirty, inside the "automation" directory we created earlier - create a new file called "my_test.js" or something similar and open it in your editor of choice (Sublime FTW!).

Start your test file with some includes by using the nodeJS method require. We need access to assert, fs (filesystem), selenium testing and the selenium webdriver.

var assert = require('assert'), 
    fs = require('fs'), 
    test = require('selenium-webdriver/testing'), 
    webdriver = require('selenium-webdriver');

Cool, now we have our requirements set out we can start writing the tests - tests are a combination of functions inside a parent function I guess there are multiple ways to do this but the idea being you could create a test for a contact page and test multiple features within the parent.

To start with, this is how a basic test setup will look:

test.describe('My Website', function(){ 
    this.timeout(15000); 
});

Notice the timeout, a tests default timeout is 2000ms so if for whatever reason the page doesn't load within that time limit the test fails so I as standard override that setting.

The test suite has the ability to perform specific actions before and after all the individual tests have completed, for instance open the browser driver (which we NEED to do) and after kill the browser. Lets add them now.

test.describe('My Website', function() {
    this.timeout(15000);
    
    var driver;
        test.before(function() {
        driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();
    });

    test.after(function() {
        driver.quit();
    });
});

Awesome! You should now be getting a feel for how a test is configured and setup - the only element missing is the actual independent tests themselves.

Writing a basic contact form test

As a quick example, we're going to write a basic test for a contact form. The concept is quite simple, load the contact page - fill in the fields - submit the form - check if success is present.

Under the test.before function we need to create a new function, test.it.

test.it('Contact form should return success', function(){ 
    driver.get('http://yourwebsite.co.uk/contact-page'); 
});

Now if you were to open your terminal/CMD prompt and CD to the directory with your JS file and run:

mocha my_test.js

You should receive a test success message.

Great! Now a quick introduction to elements... The test suite has access to multiple different functions for finding an element on a page, you can do this by class name, ID, name, CSS Selector and more - what we need to do is find the input elements and fill them in. This is achieved with the sendKeys function.

As you've seen above we can chain a set of functions together to keep the code a bit cleaner, this is how you fill in the name field on a form.

driver.findElement(webdriver.By.name('name')).sendKeys('Glenn Taylor');

Putting it all together, you will get something like this:

test.it('Contact form should return success', function() {
    driver.get('http://yourwebsite.com/contact-page');
    driver.findElement(webdriver.By.name('name')).sendKeys('Glenn Taylor');
    driver.findElement(webdriver.By.name('email')).sendKeys('[email protected]');
    driver.findElement(webdriver.By.name('message')).sendKeys('This is a test message!');
    driver.findElement(webdriver.By.className('contact-form')).submit();
    driver.wait(function() {
    return driver.isElementPresent(webdriver.By.className('success-flash'));
    }, 3000);
});

So as you can see above, we grab the contact page on our website. Fill in 3 fields and then use the submit() function on the contact-form class (which would obviously be a form) to send it off.

We then use the wait function to give the browser time to navigate to the other page and then run the isElementPresent function which returns true or false after hunting for the .success-flash message.

This should be an accurate enough test to ensure a successful submission.

Make sure the above function sits between your test.before and test.after functions and then open your terminal/CMD and once again run:

mocha my_test.js

And you should (as long as the test is geared towards your own contact form) receive a successful test pass.

Locators

A locator is a method of finding a specific element, due to a lack of documentation on the multiple options within webdriver.js here are they are:

  1. webdriver.by.className('.my-class')
  2. webdriver.by.css('#some-id')
  3. webdriver.by.id('element-id')
  4. webdriver.by.linkText('click me')
  5. webdriver.by.js
  6. webdriver.by.name('firstName')
  7. webdriver.by.partialLinkText('click')
  8. webdriver.by.tagName('a')
  9. webdriver.by.xpath()

For more information and an explanation of each function, refer to the locators.js file which is heavily documented with commenting:https://code.google.com/p/selenium/source/browse/javascript/webdriver/locators.js

I'll keep this document up-to-date with new methods I come across in the near future.

Thanks for reading! Please share and spread the word :)