Generate a CSS/Xpath selector from a WebElement?

2,616 views
Skip to first unread message

ankit

unread,
Jul 18, 2012, 11:39:30 PM7/18/12
to seleniu...@googlegroups.com
I've written a script using WebDriver which traverses through all the input/select elements on a page and returns their properties so that devs can take a look at the generated list and write tests using that. The problem is that in some cases relevant elements dont have a CSS id, so I need a way to assign them some kind of selector (preferably CSS) so that they can be referenced later. Is there a way using selenium or jQuery to obtain a CSS selector for a given WebElement object?

I'm using selenium 2.24.1 with the python API. CSS is preferable because the tests run on IE 7/8/9 so XPath selectors would be very slow.

Peter Gale

unread,
Jul 19, 2012, 3:20:51 AM7/19/12
to Selenium Users
Other than their full DOM path, elements don't have any unique ID's unless the dev's put them in against the elements themselves.

So if the dev's won't you to be able to report against each unique element with absolute clarity on which element your reports are referring to, they need to ensure that the elements are uniquely referenced with id's.

It's just a simple matter of Garbage In - Garbage Out.


Date: Wed, 18 Jul 2012 20:39:30 -0700
From: ankit...@gmail.com
To: seleniu...@googlegroups.com
Subject: [selenium-users] Generate a CSS/Xpath selector from a WebElement?


I've written a script using WebDriver which traverses through all the input/select elements on a page and returns their properties so that devs can take a look at the generated list and write tests using that. The problem is that in some cases relevant elements dont have a CSS id, so I need a way to assign them some kind of selector (preferably CSS) so that they can be referenced later. Is there a way using selenium or jQuery to obtain a CSS selector for a given WebElement object?

I'm using selenium 2.24.1 with the python API. CSS is preferable because the tests run on IE 7/8/9 so XPath selectors would be very slow.

--
You received this message because you are subscribed to the Google Groups "Selenium Users" group.
To post to this group, send email to seleniu...@googlegroups.com.
To unsubscribe from this group, send email to selenium-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/ZsZSNTn_mBoJ.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Brian Goad

unread,
Jul 24, 2012, 4:19:27 PM7/24/12
to seleniu...@googlegroups.com
Use javascript injection to add an id attribute that you create to the element.

Brian

ankit

unread,
Aug 6, 2012, 12:29:48 PM8/6/12
to seleniu...@googlegroups.com
I ended up writing some JS code to do the job for me:
jQuery.fn.getPath = function () {
    if (this.length != 1) throw 'Requires one element.';

    var path, node = this;
    while (node.length) {
        var realNode = node[0], name = realNode.localName;
        if (!name) break;

        name = name.toLowerCase();
        if (realNode.id) {
            // As soon as an id is found, there's no need to specify more.
            return name + '#' + realNode.id + (path ? '>' + path : '');
        } else if (realNode.className) {
            name += '.' + realNode.className.split(/\s+/).join('.');
        }

        var parent = node.parent(), siblings = parent.children(name);
        if (siblings.length > 1) name += ':eq(' + siblings.index(node) + ')';
        path = name + (path ? '>' + path : '');

        node = parent;
    }

    return path;
};
//This return is valid since execute_script() executes the given JS in the body of an anonymous function
return "done";




On Wednesday, July 18, 2012 11:39:30 PM UTC-4, ankit wrote:

Peter Gale

unread,
Aug 6, 2012, 12:47:10 PM8/6/12
to Selenium Users
Does this generate something useful for any web page? Or is it only of use for the particular page you are looking at?

How does it differentiate two elements with no id and the same set of class attributes?

Could you show us some example input/output?

What happens if (or when) the developers) change the classes on the elements?

I can't help but feel that if you're initiating the call from a WebElement, it would have been better written in the host language (java?) with just WebDriver calls.


Date: Mon, 6 Aug 2012 09:29:48 -0700
From: ankit...@gmail.com
To: seleniu...@googlegroups.com
Subject: [selenium-users] Re: Generate a CSS/Xpath selector from a WebElement?
--
You received this message because you are subscribed to the Google Groups "Selenium Users" group.
To post to this group, send email to seleniu...@googlegroups.com.
To unsubscribe from this group, send email to selenium-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/JZghOMCLtEsJ.

ankit

unread,
Aug 6, 2012, 4:11:27 PM8/6/12
to seleniu...@googlegroups.com
It should be useful for any scenario where you want a CSS path for an element you can get through jQuery. I'm not sure what you're asking here. At the end of the day, it's upto the dev to judge whether its useful or not. 

It uses the :eq() pseudo-selector to differentiate elements when all else fails. That should be enough to differentiate any set of elements.

Example Usage:
HTML:
<html>
<head><title>Test</title></head>
<body>
<div id="container1">
<p class="testclass">A</p>
<p class="testclass">B</p>
</div>
</body>
</html>
$('p:contains(A)').getPath() => "div#container>p.bla:eq(0)"
$('p:contains(B)').getPath() => "div#container>p.bla:eq(1)"

If they change the classes, then the selectors are no longer valid. The way its used in my application is that a traversal script generates these for each element of interest on a page, and tests are auto-generated from the results of that script, so its not a concern. If the classes, or anything else on the page changes, the traversal script will run again and regenerate the right selectors. This is why I can get away with insanely specific selectors too.

I think it would be better to do this using WebDriver calls only, but I could not find a good way to do this. An important concern to keep in mind for me was that WebDriver uses a browsers native CSS engine by default (and Sizzle if none exists), so the selectors generated this way (if possible, I have not looked into this) would be browser specific. jQuery selectors work universally. In general, liberally using jQuery makes tests a lot cleaner and platform independent IMO, so I don't shy away from using it.

On Monday, August 6, 2012 12:47:10 PM UTC-4, PeterJef...@Hotmail.co.uk wrote:
Does this generate something useful for any web page? Or is it only of use for the particular page you are looking at?

How does it differentiate two elements with no id and the same set of class attributes?

Could you show us some example input/output?

What happens if (or when) the developers) change the classes on the elements?

I can't help but feel that if you're initiating the call from a WebElement, it would have been better written in the host language (java?) with just WebDriver calls.


Date: Mon, 6 Aug 2012 09:29:48 -0700
From: ankit...@gmail.com
To post to this group, send email to selenium-users@googlegroups.com.
To unsubscribe from this group, send email to selenium-users+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages