Wednesday, 30 June 2010

What if Selenium's Highlight Command was always on?

A reader asked for recommendations on how to use Selenium's "Highlight" command. Now I personally don't use the highlight function. Never really have. When I debug my tests, I step through the script in Eclipse (I write all my tests in Selenium-RC using Java).
But, by using reflection to automatically generate code for a java class we can run the highlight command prior to executing other Selenium commands, without amending our existing tests. And answer the question, "what if Selenium's Highlight Command was always on?"


The Question

Putting my e-book "Selenium Simplified" out as a beta release has meant that I have received lots of great questions from people learning Selenium, most of these answers I add in to the book, but some I deal with through private emails and blog posts. In this case a reader asked for recommendations on how to use Selenium's "Highlight" command.
The highlight command in Selenium takes a locator as a parameter and flashes the control yellow. A small helper function added to help debugging so you have some indication of what elements your script touches.

Now I personally don't use the highlight function. Never really have. When I debug, I step through the script in Eclipse (I write all my tests in Selenium-RC using Java). If this method of debugging doesn't reveal the problem then a high probability exists  that my issues relate to a timing problem (stepping through adjusts the timing of the test so sometimes you can't reveal the problem that way).
I can see why you might want to to highlight the locator elements in use at the time and error happens, if you take screenshots automatically when a test fails. And this is discussed by Phil Smith.
So I thought I'd try the highlight function out and, by taking a leaf from Marvel's  "What If...?" comic, answer the question "What if Selenium's Highlight Command was always on".

The Approach

One easy way to retrofit the highlight command into your tests involves extending the DefaultSelenium class. You can find a detailed explanation of this approach in an article by Mahesh Narayanan.
And rather than build this HighlighterSelenium class by hand, I thought that it would make more sense to generate the class automatically.
This would have the advantages that:
  • Whatever version of Selenium I use, the generated code will match it
  • I don't have to debug every individual message
  • I find it more interesting to write code generation code than wrapper code
If you haven't used Reflection in Java then I'll give a quick overview. In Java reflection allows us to access the class definitions, so rather than creating an instance of a class as an object and calling methods on the object. I can access the class definition and see what methods the class supports, get lists of the parameters etc.
As a quick example, if I want to get all the constructors for a class
Class<DefaultSelenium> seleniumClass = DefaultSelenium.class;
Constructor[] allConstructors = seleniumClass.getDeclaredConstructors());
And then I can cycle through the array of constructors and display them.
So to build the code for HighlighterSelenium I simply replicate the constructors and methods on DefaultSelenium, and for each method I want to highlight I add something like the following as the body of the method:
highlight(locator); super.methodName(locator);
e.g.
public void click(java.lang.String p0){highlight(p0);super.click(p0);}
I would not manually code it like this, I would use imports in the class file and more spacing and indentation, but with code generation I don't have to worry overly much about the human aesthetic reaction to the code.

The Implementation

In the linked source code folder you will find a BuildSeleniumLocatorHighlighter.java class.

This contains a test which when run, will output to stdout the code for HighlighterSelenium, automatically generated from whatever version of the Selenium jar you have associated with the project.

So to use this, if you to want to experience "The Day Selenium Highlight Took Over" (example assumes you use eclipse):
  • download the source code archive
  • add BuildSeleniumLocatorHighlighter.java to a project all setup with tests and Selenium libraries in the build path
  • run the reflectThroughSelenium test
  • copy the output from stdout in the console into a new class file "HighlighterSelenium.java"
  • in your tests, instead of creating an instance of DefaultSelenium, create an instance of HighlighterSelenium
  • then run your tests
An lo, doth hilarity ensue.

My Answer

Having done this and run my tests, I didn't feel like I got any real benefit from the highlight command. If I ever do need to use it then I'll dig out HighlighterSelenium class as that might help, and at the very least means I don't have to do any coding work to amend my tests to highlight the locators.
If you look at the generated source code you will see that some of the methods don't have highlight code - these either don't use a locator, or the user does not expect it to throw an exception when the locator does not find an element.
The BuildSeleniumLocatorHighlighter.java class should also act as a good introduction to reflection.
Tip:
I very often write small apps and scripts like this as "tests" in Java. This way I can run them easily from the eclipse right click menu. It seems an easy way to get the adhoc scripting benefits that people get from Ruby and Perl.
Shameless Plug:
If you want to learn selenium, but don't have the programming skills, then you might find my e-book "Selenium Simplified" useful. It walks you through the learning process so that you go from "no programming ability" to "writing Selenium-RC tests in Java" very quickly. For more information, and to read a free preview of the book, visit http://www.compendiumdev.co.uk/selenium
Related Links:

No comments:

Post a Comment