(This is the second installment in my series on the basics of how to use Selenium and Mocha to perform functional tests on your web applications. For the previous article, click here.)
In today’s post, we’ll using Mocha and Selenium to test a basic sample application. Before getting into that however, you will need to download a few things:
Step 1: Install Node JS
If you haven’t already, install Node JS by following the instructions on http://nodejs.org/.
Step 2: Download Selenium
Selenium is a tool that automates web browsers, allowing us to run our functional tests against a real instance of a browser. It currently supports a number of versions of Internet Explorer, Firefox, as well as Google Chrome and Opera (although some of these require third party written code – for a full supported list of browsers go to here). At the core of how Selenium works is the Selenium Server, which is responsible for the execution of automation commands to the browser. A Selenium client can then connect to the server, and instruct it to perform a variety of different actions (ie. clicking a button, going to a URL, etc) or to retrieve information about the current state of the browser (such as using CSS selectors to retrieve elements, inspect text, and so on). The real advantage to this is that it allows for language specific clients (or WebDrivers) which allow for automation scripts to be written in a developer’s (or tester’s) language of choice, be it Ruby, Java, Python, C# or now, thanks to the experiemental WebDriverJS client, Javascript.
For the purposes of this article, you will to download the Selenium Server from the Selenium downloads page, and assuming that you have Java installed, you can then fire it up by running -
java -jar <path to the Selenium JAR file>
You should see the Selenium server load up, and be ready to start serving tests.
Step 3: Get the sample application
Now that we’ve got the base dependencies installed, you can either checkout my example project from my GitHub repository, or create your own simple application to test. My sample application is a very simple Express application running on Node, which we’ll be testing using Selenium and Mocha.
Before running the application, you’ll first have to install the module dependencies. This is done through the use of NPM (Node Package Manager – an exceptional tool for managing dependencies which is included with the Node JS installation) by running -
npm install
Once the dependencies, you can start up the application server by running -
node app.js
Navigate to http://localhost:3000 and you should see the application running as in the image below.
It is a very simple ’Library’ index application – it consists of a home page, a books page with a list of books, and an authors page, with a list of authors. Links on each of the pages control the user’s navigation.
Before we get onto writing the tests proper, there were a few modules that were installed by NPM that are worth knowing about at this point.
Mocha
Mocha is an exceptional test framework for Node.js (as well as browser based) testing developed by TJ Holowaychuk – author of the Express web framework for Node. It allows for a comprehensive suite of test functionality and reporting that makes writing tests almost enjoyable – not quite, but about as close as you can get! While I have indicated that Mocha is to be installed as a development dependency of my sample application, you can also install it manually using the following command -
npm install mocha(or npm install -g mocha to install to the global NPM repository)
Chai
Once we have Mocha, we can also choose an assertion library to allow us to evaluate our test assertions – my personal favourite is Chai, which allows for BDD/TDD style assertions and works well with Mocha. Chai can be installed via NPM as well, using the following command:
npm install chai
WebdriverJS
As mentioned in my first article, to communicate with the Selenium server from Javascript, you have a number of choices. The first is to take advantage of the WebDriverJS web driver for Selenium. In order to use this driver, you will have to checkout the Selenium source code from the SVN repository, and then build the WebDriverJS by following the instructions on the wiki.
The second one I’ll mention, and the one that we will use for the remainder of this article, is the webdriverjs NPM module written by Camilo Tapia, which utilizes the Selenium JSON Wire Protocol to communicate with the Selenium server.
There are few reasons as to why I chose the Camilo’s module over the standard WebDriverJS module. Primarily however, I believe that tests should be as easy to write as possible, and while the same functionality is present in both, Camilo’s module makes writing tests, and adding custom functionality a much more pleasant experience than the verbosity involved with working with the standard WebDriverJS module.
Step 4: Run some Selenium tests
So now that we’ve got our application all up and running, let’s run some tests to test that it’s working correctly. We’ll run one of the tests that’s included with the sample project – simple_test.js. This test will simply navigate to the page, and test to see if the title equals ‘Library’. To run the test, use the following command from the root directory of the sample project:
mocha tests/simple_test.js -t 30000
You should see the application fire up in Firefox (this can be configured to other browsers), and you should see Mocha complete the test successfully. If you find that Firefox takes a while to start up, and Mocha times the test out before completing successfully, you may have to increase the value of -t in the above command. (the value is in milliseconds so 30000 = 30 seconds)
Let’s take a look at the guts of this test to see what’s happening:
before(function(done) {
// Add some helper commands
client.addCommand('hasText', function(selector, text, callback) {
this.getText(selector, function(result) {
expect(result.value).to.have.string(text);
callback();
});
});
done();
});
The before() function in Mocha allows us to setup code that runs before the tests are run. In this instance, we are using it to add a custom command to the webdriverjs client to allow it to have a .hasText function that will use Selenium to get the text of an element on the page, and then use a Chai assertion to assert whether it is the value we expected or not.
beforeEach(function(done) {
// Navigate to the URL for each test
client.init();
client.url('http://localhost:3000', done);
});
The beforeEach function get’s executed before each test is run. In this case, it sets up the webdriverjs client, and instructs it to go to the application URL before actually starting the test.
it('should be able to view the home page', function(done) {
this.timeout(10000);
client.hasText('#title', 'Library');
done();
});
The code above forms the actual content of the test. The this.timeout function instructs Mocha that it should fail the test if it hasn’t finished within 10 seconds. We then use the .hasText function that we added in the before() function to assert that the title element has the text ‘Library’. If it didn’t have the matching text, the test would have failed.
afterEach(function(done) {
client.end();
done();
});
After the test has finished (or failed), Mocha runs the afterEach function, which we use to clean up the Selenium sessions that were created over the course of the tests.
And that’s it – a Mocha test that uses Selenium to test a web application in the browser!
What next?
This has been a very simple demonstration of Mocha and Selenium and of course, any real test would be expected to do things like clicking links, uploading files, waiting for elements to appear/disappear – all of which is possible. For starters, if you are interested, you may wish to check out the slightly more complicated page_test.js file in the repository, which tests the navigation of the sample application.
Alternatively, additional reading resources can be found at:
- Selenium (http://seleniumhq.org/)
- WebDriverJS (http://code.google.com/p/selenium/wiki/WebDriverJs)
- WebDriverJS – Selenium Bindings for Node.js (https://github.com/Camme/webdriverjs)
- Mocha (https://github.com/visionmedia/mocha)
- Chai (http://chaijs.com/)
If this article has interested you, you may wish to follow me on Twitter (@noehlman), or you may wish to browse the random collections of code on my GitHub repository.
