Testing Across Browsers with JavaScript and Webdriver
Peter Braden on
Thursday, January 19, 2012 at 1:31PM Although jQuery has done a lot to minimise cross browser DOM inconsistencies, sometimes you run into an area where there is still little browser consensus, and you have to experiment with each one.
Until recently, I dreaded this scenario; booting up a VM with an antiquated operating system to run a browser from last decade, made the days when I ran into browser problems stressful and long. And at Yammer we like to push browsers to the limit in pursuit of a great product, so these days were all too common.
On a recent project, which touched both content-editable elements, and manipulation of selections and ranges (both areas where most browsers disagree), I decided there had to be a better way, and came up with a test mechanism which took almost all the pain out of writing cross-browser code.
While none of the concepts are that unique, it's an easy technique that I plan to use more often.
I was prototyping a rich-text editor using content-editable divs. Those of you who have dived into this area are familiar with the completely different way browsers handle content-editable. In a bizarre turn of events, Internet Explorer actually has one of the more sane implementations.
I decided that, due to the inconsistencies, I was going to code test-first; that is, first write failing unit tests, and then fix them in each browser.
I was writing javascript, thus ideally I wanted my tests to also be in javascript — the less context switching the better when writing unit tests.
The most reliable system for cross browser testing at the moment is the Selenium project. I had very little interest in generating Selenium tests, but luckily the Selenium server speaks a simple language called the Web Driver protocol. Based around an earlier Google project for scripting browser interaction, Web Driver allows you to control a browser and run arbitrary javascript, using a simple set of commands.
Even better, there is a NodeJS module called wd that already implements this protocol in javascript. The pieces were all there and all I had to do was glue them together.
And there was remarkably little glue required. I didn't even have to set up a Selenium server- Yammer already has a Sauce Labs account for running other unit-tests, and this meant that I could simply plug in our creds and spawn whatever VM's and browsers I desired in the Sauce cloud.
I wrote a very simple test runner to run the tests synchronously, and a set of simple unit tests. With a single command in the terminal, they were running concurrently in each browser.
By testing very basic assumptions, locating the point where DOM implementations diverged was super easy. And with what seemed like very little effort, I was able to get a complicated and DOM heavy piece of code written and reliable.
To show you how simple it is to get the tests running, I thought it'd be cool to get you to run them now. SauceLabs have let me set up a public account so that you can run them on their test infrastructure. (They'll probably shut the account down in a few days, so if you're reading this later, you may have to open your own account).
All that you need to do is to clone my repo:
git clone git@github.com:yammer/Editable-Content.git
and then run:
node test/run.js --username yammer-demo --apikey 145c4ffa-8d74-4fd5-8905-25dcbf546e97 --browser firefox,iexplore@7,iexplore@8,googlechrome
The tests are now running. Each dot is a test completing successfully, and if your terminal supports colors, each color represents a browser. I've left a couple of failing tests in there so you can see the tracebacks. When running the tests on saucelabs, you get a link to a video of the tests being run so you can go back and watch the tests fail.
I'm excited that testing is becoming this easy. I hope that some of you reading, will take this and make it even better. And if you're interested in writing and testing great web apps, you should come interview with us here at Yammer. (Tell them Peter referred you ☺)
browser,
javascript,
selenium,
testing,
webdriver 





