Going Atomic: How
This is the second of my technical posts. Again, if you’re interested in the internal workings of Selenium 2, then please skip straight to something else. If you’re interested in how and why we made some of the technical decisions on the project, keep reading….
We left our intrepid heroes in a tight spot: they’d decided to write a shared library of code, to be used by the various webdriver implementations and selenium core, but the requirements for doing this seemed to be at odds with it actually happening.
Fortunately, at about the same time we started down this path, Google Open Sourced the Closure compiler. This is a Javascript compiler that takes as input a set of Javascript files, and which outputs Javascript. It can be configured to either pass the code through untouched into a single file, or it can compile a script aggressively, removing unused code-paths and minifying the output as much as possible. The Closure compiler is used on a lot of Google products, so we know that it’s reliable and consistent.
In order to get the best out of the Closure compiler, we’re writing the atoms using the Closure library. This isn’t as well known as some of the other JS libraries out there, but it’s solid, well tested and is being actively developed. It also features an easy-to-use extension of JsUnit, which makes writing tests a far simpler task than might otherwise be the case, and it has an easy to use mechanism for modularizing code.
So, given that we could compile a single Javascript function (and it’s dependencies) into a minified fragment of JS, we were all set, right? Not quite.
The problem is that the atoms are being extracted from two frameworks that have a different way of viewing the world. As an example, Selenium 1’s “getAttribute” method only returns the value of a particular attribute, whereas WebDriver’s “getAttribute” method will return the value of either a property or an attribute (because sometimes it’s hard to remember whether something is an attribute or a property of an element)
As with all problems in computer science, an extra level of indirection is used to solve this issue.
We’re busy implementing the expected behaviour of both WebDriver’s and Selenium’s API on top of the atoms.
There is, of course, the obvious question about how we get this carefully compressed JS into a driver. One option would be to include the raw Javascript as files in each language binding, and pull them in as required. That’s possible, but it would make each language binding bloated, and would introduce a lot of duplication. The alternative is to push the atoms as far into the driver as possible, and this is what we do. As part of the build process for webdriver, we take the compressed JS and convert it into a form that can be consumed by a particular driver. For example, for the IE driver, we convert them into constants in a C header file. These constants can then be referred to by the driver and converted back into a script than be executed via the same mechanism that is used by “executeScript”.
What do we gain from this seemingly baroque approach? Other than the ability to share the same code between drivers? Many things. The cost of maintenance drops dramatically as we can fix a bug in one place and have that fix be picked up by every driver. Because we’re working in pure JS and just querying the DOM, we can run the unit tests in a browser whilst we’re developing the code. This leads to a very tight feedback cycle. It also makes it easier for developers not familiar with the code to take a look at how we do things, and send us patches (always appreciated!) Finally, we can ensure a consistency of result.
Right, any questions?
A Smattering of Selenium #25
A day late, but that sort of thing happens when you have family.
- I keep telling myself I will document how to incorporate Se launching and result recording in QC, but never seem to find the excuse. Looks like Aaron found the excuse: Finding the API for a DLL, Connecting to HP/Mercury Quality Center from a client side script
- Also from Aaron is a cool Credit Card Generator which has nice id tags which makes for easy Se parsing. Though I would argue that rather than open a new browser for this you send a URL get or similar, but this works as well.
- David continues to post about his employer’s ‘Elastic Build System’ in the context of Se-Grid in Nimble Test Clusters
- Having had, and then mutually cancelling a book deal on Se, its a delight to see Overview of Selenium 1.0 Testing Tools: Beginner’s Guide now available in ‘beta’. Guess you need to finish it now, eh David?
- easy setup for your cucumber scenarios using headless gem run selenium your ci server is in the context of cucumber, but could be easily ported to other things I suspect.
- Another I-switch-to-Se2-and-liked-it post, this time from Ben at Switching from Selenium 1.x to WebDriver/Selenium 2 and HtmlUnit
- howfuckedismydatabase is just plain funny. And who of us hasn’t asked that very question – usually at some less than optimal time
- The September gathering of Chicago ALT.NET is on September 8 and is going to be on Selenium 101.3: Practical Functional Testing Techniques
- Testing Flash With Selenium talks about the standard ExternalInterface stuff, but most important is the last sentence: So, if your app has less functions that needs to tested, you can use this approach, if not, testing manually will be the better option.. Just because you can, doesn’t mean you should (more insight into the life of Selenium consultant…)
- Another framework! This time it is Selena.
- An over-the-should problem-solution post on getting started with Se – FMK vs Selenium. Worth also checking out the ‘Modeling Portfolio’ for the, erm, interesting hairstyles he has tried on himself
- Seems like Yeti and Se should work well together, though I can’t quite figure out why/how. And for those with small kids, the Yeti Stomp might also be familiar.
A Smattering of Selenium #24
A bit late, but I’m in California for a Selenium Developers Meetup and my body doesn’t quite know where it is temporally.
- Don’t forget that tomorrow is the next meeting of the San Francisco Selenium folks which seems to be running a crowd sourced “Let’s stump Jason with our problems” session. Most of the ‘main’ Se folk will be there.
- Test design theory is something that I have yet to really see covered much, so here are three articles on the similar idea of what to test and what to skip.
- Contradiction: Test Everything, but not Accessors? by Ron Jeffries
- don’t test for blocking conditions: an example by Chris McMahon
- Every automated test should do ONE thing really well by Adam Goucher (me)
- Another simple build radiator is just a darn cool re-skinning of Hudson which, while not as fun, is super useful in communicating build status
- Simon started to explain some of the work going on in the guts of Selenium WebDriver in Going Atomic: Why?
- For those people who loiter in the #selenium irc channel, you have likely seen ‘selbot’ in action. If you wondered where it came from you can read the details from Sauce Labs in Introducing selbot
- Atlassian is a pretty big user of Se and has a post called push my buttons which explains the myriad of ways you can send a key in Se 1.x. Which IIRC is one of the major improvements that Se 2 provides.
- The march of Flex Pilot continues and so the blog posts from users are starting to appear including Selenium Testing with Flex Pilot
- I was pleading for help on twitter last week and this cool use of the JUnit 4 @Rule annotation to get screenshots on test failures was provided
- If you are using CruiseControl.NET then Integrating Selenium Tests into CruiseControl.Net via NUnit is likely going to deliver value
- Silverlight UI testing with Selenium and Ruby is the first article I think I have seen on the subject. Of course, my memory isn’t so hot at time…