Search This Blog

Subscribe:

Thursday, October 28, 2010

Extending Selenium server with custom commands

In this posting I document extending Selenium server with a custom javascript method, getAllRadios(), to return all radio button elements in a page. It’s based on the getAllButtons() that is stock in Selenium.

I will demonstrate two ways to add this custom method. The first strategy is to add the custom method to the native javascript files that ship with Selenium server. This is not the recommended way to extend Selenium but it is an almost guaranteed way to be sure the server picks up my new method and that frees me to focus on getting my client syntax right for calling the new method using the client’s doCommand() method.

Method 1 – selenium-browserbot.js + selenium-api.js

Unpack the server jar into a temporary directory to get access to the selenium-browserbot.js and selenium-api.js files.

[20:54 20090906 crashing@server /selenium-server-1.0.1/temp]
$ jar xf ../selenium-server.jar

The new custom method is added to core/scripts/selenium-browserbot.js. It is a slightly modified version of getAllButtons() which is defined in the same file.

BrowserBot.prototype.getAllRadios = function() {
var elements = this.getDocument().getElementsByTagName('input');
var result = [];
for (var i = 0; i < elements.length; i++) {
if (elements[i].type == 'radio') {
result.push(elements[i].id);
}
}
return result;
};

and then the new method is exposed to the Selenium API in core/scripts/selenium-api.js, again modeling after getAllButtons() in selenium-api.js.

Selenium.prototype.getAllRadios = function() {
return this.browserbot.getAllButtons();
};

Now rebundle the updated javascript into a new server jar, replacing the original.

[21:01 20090906 crashing@server /selenium-server-1.0.1/temp]
$ jar cmf META-INF/MANIFEST.MF ../selenium-server.jar .

Method 2 – user-extension.js

The better way to extend Selenium is to add methods to the user-extensions.js file. This avoids screwing around with the native server jar. I initiall had some trouble getting this working, hence the Method 1 approach, but after a bit of futzing I finally got this to work.

Selenium.prototype.getAllRadios = function() {
var elements = this.browserbot.getDocument().getElementsByTagName('input');
var result = [];
for (var i = 0; i < elements.length; i++) {
if (elements[i].type == 'radio') {
result.push(elements[i].id);
}
}
return result;
};

This is basically the same method used in selenium-browserbot.js. The important changed bits are (1) the method is attached to the Selenium object instead of the BrowserBot (Selenium.prototype rather than BrowserBot.prototype) and (2) calling getDocument() on the browserbot instance.

I start the Selenium server with the -userExtensions option pointing to the user-extensions.js file.

java -jar \
/selenium-server-1.0.1/selenium-server.jar \
-userExtensions /user-extensions.js

Client Coding

For either of the above methods of extending the Selenium server, I call this new method in my client code with the doCommand().

/** incomplete code **/

proc = new HttpCommandProcessor(seleniumServerHost,
seleniumServerPort, brower, seleniumServerStartUrl);
selenium = new DefaultSelenium(proc);

selenium.open(url);

// radio buttons returned as comma-delimited strings
String allRadios = proc.doCommand("getAllRadios", null);

// alternatively, get radio buttons as a String array
String[] radios = proc.getStringArray("getAllRadios", null);
for (String radio : radios) {
System.out.println(radio);
}

To call custom doCommand()‘s, it’s necessary to instantiate with DefaultSelenium(proc) to inject the HttpCommandProcessor into the DefaultSelenium object.

Tuesday, October 26, 2010

Use regex in Selenium locators

To use regex in Xpath locators.

You need to use the regex matches() function, like this:

xpath=//div[matches(@id,'che.*boxes')]



this will click the div with 'id=checkboxes', or 'id=cheANYTHINGHEREboxes')
To get all the links elements with attribute href that match:
http://[^/]*\d+com

Use
sel.get_attribute( '//a[regx:match(@href,
"http://[^/]*\d+.com")]/@name'
)
which will
return a list of the name attribute of
all the links that match the regex.

Be aware, that the matches function is not supported by all
native browser implementations of Xpath
(most conspicuously, using this in FF3 will throw an error: invalid xpath[2]).
If you have trouble with your particular browser (as I did with FF3), try using Selenium's allowNativeXpath("false") to switch over to the JavaScript Xpath interpreter. It'll be slower,
but it does seem to work with more Xpath functions, including 'matches' and 'ends-with'.




Friday, October 22, 2010

Installing ANT on Windows

1. Download ANT

2. Unzip the zip file and put it in your comfortable folder (say D:/ant/)

3. Set ANT_HOME environment variable to the Ant location

(MyComputer Rt.Click >> Properties >> Advanced >> Environment Variables >> User Variables for Administrator >> Set New Variable Name as "ANT_HOME" and set New Variable Value as D:/ant)

4. Now set Path variable to point to your ANT bin directory

(User Variables for Administrator >> Click on Path variable >> Append the ANT bin directory location , say%ANT_HOME%\bin)

5. Open a command prompt and type "ant" , you should see it working now . In case of any failure try the below command and see the value for ANT_HOME

c:\echo %ANT_HOME% // This should print your current ANT directory