e2e or end-to-end or UI testing is a methodology used to test whether the flow of an application is performing as designed from start to finish. In simple words, it is testing of your application from the user endpoint where the whole system is a blackbox with only the UI exposed to the user.
It can become quite an overhead if done manually and if your application has a large number of interactions/pages to test.
In the rest of the article I’ll talk about webdriverJS and Jasmine to automate your e2e testing, a combination which isn’t talked about much on the web.
What is WebDriverJS?
This was something which took me quite sometime to put my head around and I feel this was more or less due to the various available options for everything related to WebDriver.
So let’s take it from the top and see what its all about.
As mentioned on the selenium website, Selenium automates browsers. That’s it.
This having support for almost all major browsers, is a very good alternative to automate our tests in the browser. So whatever you do in the browser while testing your application, like navigating to pages, clicking a button, writing text in input boxes, submitting forms etc, can be automated using Selenium.
WebDriver (or Selenium 2) basically refers to the language bindings and the implementations of the individual browser controlling code.
WebDriver introduces a JSON wire protocol for various language bindings to communicate with the browser controller.
For example, to click an element in the browser, the binding will send POST request on
So, at one end there is the language binding and a server, known as Selenium server, on the other. Both communicate using the JSON wire protocol.
So as you might guess, WebDriverJS is simply a wrapper over the JSON wire protocol exposing high level functions to make our life easy.
Now if you search webdriver JS on the web, you’ll come across 2 different bindings namely selenium-webdriver and webdriverjs (yeah, lots of driver), both available as node modules. You can use anyone you like, though we’ll stick to the official one i.e. selenium-webdriver.
Done! You can now require the package and with a lil’ configuration you can open any webpage in the browser:
To run your test file, all you do is:
Note: In addition to the npm package, you will need to download the WebDriver implementations you wish to utilize. As of 2.34.0, selenium-webdriver natively supports the ChromeDriver. Simply download a copy and make sure it can be found on your PATH. The other drivers (e.g. Firefox, Internet Explorer, and Safari), still require the standalone Selenium server.
Difference from other language bindings
WebDriverJS has an important difference from other bindings in any other language - It is asynchronous.
So if you had done the following in python:
But it doesn’t stop here. Even with promises, the above code would have become:
Do you smell callback hell in there? To make it more neat, WebDriverJS has a wrapper for Promise called as ControlFlow.
In simple words, this is how ControlFlow prevents callback hell:
- It maintains a list of schedule actions.
- The exposed functions in WebDriverJS do not actually do their stuff, instead they just push the required action into the above mentioned list.
- ControlFlow puts every new entry in the
thencallback of the last entry of the list, thus ensuring the sequence between them.
And so, it enables us to simply do:
Isn’t that awesome!
Controlflow also provides an
execute function to push your custom function inside the execution list and the return value of that function is used to resolve/reject that particular execution. So you can use promises and do any asynchronous thing in your custom code:
Combining WebDriverJS with Jasmine
Our browser automation is setup with selenium. Now we need a testing framework to handle our tests. That is where Jasmine comes in.
If we were to convert our earlier
testfile.js to check for correct page title, here is what it might look like:
Now the above file needs to be run with jasmine-node, like so:
This will fire the browser and do the mentioned operations, but you’ll notice that Jasmine won’t give any results for the test. Why?
Well…that happens because Jasmine has finished executing and no
expect statement ever executed because of the expectation being inside an asynchronous callback of
To solve such asynchronicity in our tests, jasmine-node provides a way to tell that a particular
it block is asynchronous. It is done by accepting a done callback in the specification (
it function) which makes Jasmine wait for the
done() to be executed. So here is how we fix the above code:
Quick tip: You might want to tweak the time allowed for tests to complete in Jasmine like so:
Bonus for Angular apps
Angular framework has been very testing focused since the very beginning. Needless to say, they have devoted a lot of time on e2e testing as well.
Protractor is a library by the Angular team which is a wrapper on WebDriverJS and Jasmine and is specifically tailored to make testing of Angular apps a breeze.
Checkout some of the neat addons it gives you:
Apart from querying element based on id, css selector, xpath etc, it lets you query on basis of binding, model, repeater etc. Sweet!
It has Jasmine’s
expectfunction patched to accept promises. So, for example, in our previous test where we were checking for title:
can be refactored to a much cleaner:
And more such cool stuff to make end-to-end testing for Angular apps super-easy.
In the end
e2e testing is important for the apps being written today and hence it becomes important for it to be automated and at the same time fun and easy to perform. There are numerous tools available for you to choose and this article talks about one such tool combination.
Hope this helps you get started. So what are you waiting for, lets write some end-to-end tests!
Using an e2e testing stack you want to share? Let us know in the comments.
Links & references
WebDriverJS user guide: https://code.google.com/p/selenium/wiki/WebDriverJs
JSON wire protocol: https://code.google.com/p/selenium/wiki/JsonWireProtocol