Saturday, July 25, 2009

xpath not working in selenium RC? 'descendant' axes to the rescue

You will encounter many instances where the xpath expression for an element works perfectly well in IDE but won't work in Selenium RC. Also there will be instances where the xpath expression works well in IDE and RC for the chrome, firefox browser's but won't work in internet explorer. I will now demonstrate one such case.
Navigate to openQA forum . Now lets say that you wish to click on the 3rd instance of the image that has "/avatar/22.png?a=-1" in it's src tag. I'm talking about member icon next to every thread on the left hand side. See below, the image i'm taking about is highlighted in red.



Now the xpath for this element would be
xpath=(//img[contains(@src,'/avatar/22.png?a=-1')])[3]
I used firebug to determine that all such images on this page contain
"/avatar/22.png?a=-1" in their src tag.

now if you enter the instruction
click xpath=(//img[contains(@src,'/avatar/22.png?a=-1')])[3]
in IDE and click the find button it will highlight the image of our interest. And when you run the script it will promptly click on this image and take you to the profile page of that member whoever that may be.

The problem arises when you try to run this in RC. Below is the test method that tries to do the same.

import com.thoughtworks.selenium.*;
import org.testng.annotations.*;

public class TestContainsPredicateInXPATH {
@Test public void clickThirdMemberImage() throws Exception {
DefaultSelenium selenium =new DefaultSelenium("localhost",4444,"*firefox","http://clearspace.openqa.org");
selenium.start();
selenium.open("/index.jspa");
selenium.waitForPageToLoad("90000");
selenium.click("xpath=(//img[contains(@src,'/avatar/22.png?a=-1')])[3]");
selenium.waitForPageToLoad("90000");
selenium.close();

}
}

When you run this it will throw the error
ERROR: Element xpath=(//img[contains(@src,'/avatar/22.png?a=-1')])[3] not found

to make this work we need to tweak the xpath a little to

xpath=/descendant::img[contains(@src,'/avatar/22.png?a=-1')][3]

In the above expression the '//' have been replaced with '/descendant::' and the simple brackets after the '=' expression is gone. so the instruction now becomes

selenium.click("xpath=/descendant::img[contains(@src,'/avatar/22.png?a=-1')][3]");

Give it a try and it will work like a charm. This fix is needed whenever your xpath expressions contains functions such as 'contains', 'start-with' etc. I would recommend using /descendant axis instead of '//' on all xpath expressions that start with '//' .

4 Comments:

А.Б. said...
This comment has been removed by the author.
А.Б. said...

Hi, similar issue is found and registered in OpenQA bug tracker: http://jira.openqa.org/browse/SEL-692.

So we have a chance that one day it will be fiexed...

nothing said...

I used to it. but i can't work. please help me

nothing said...

I used selenium RC with python language, and i have problem identify locator of object. I have 2 links with code HTML
1.
a class="button button_edit" href="acct_edit?sessionID=d9PM79KCPOuh2avd&a=aaa"

2.
a href="javascript:acct_del('cus_?sessionID=d9PM79KCPOuh2avd','aaa');" class="button button_remove"

And I used Selenium IDE to identify locator of 2 links. And I have 2 locators:
1.
locator1 = "//a[matches(@href, 'acct_edit\?sessionID=[\w]*&a=" + Name + "')]"
With Name = aaa

2.
locator2 = "//a[matches(@href, \"javascript:acct_del('cus\?sessionID=[\w]*','" + name + "');\")]"
with name = aaa


And I playback with 2 locators only locator1 executed well. and locator2 is not found

I don't know what happend. Please help me..