Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium - walking up the dom tree

I'm working in python with unittest and Selenium RC on a monster web app (4 meg load).

I start out with something like

xp = '//div[id="kahoona"]//button[text()="Big"]'
selenium.click(xp)

which is fine until one of our developers starts tinkering with things like moving the javascript event handler(s) up the tree to some parent element 8 levels up. At that point Selenium's click just errors out. They also randomly insert and remove levels so 8 levels up today is 6 tomorrow and 9 the day after.

This creates a nightmare as I have to go decode the extjs generated spaghetti and one at a time move up one level - a new xpath each time, and run the test again until the errors stop.

What I want to do is, given some html that might look like this today - only the endpoints are certain - (some elements will have ids or classes and some will not):

'//div[id="kahoona"]//div//table//tr//td//div//div//div//button[text()="Big"]'

I need to find a way, starting at the button and using Selenium, walk up the dom tree (which is unknown and changes because of the aforementioned tinkering) to the outer wrapper and try something like selenium.click( the_current_xpath ) at each level until it no longer fails. At that point, I should have an xpath that works.

If this can be done relatively efficiently, I can write adaptive tests that work around the endless tinkering. The developers do their own thing - I have no influence nor can I access the source.

Any suggestions very welcome.

like image 609
Mouse Food Avatar asked Oct 23 '25 23:10

Mouse Food


2 Answers

By using xpath:

//button[text()="Big"/parent::*

it will walk up 1 level from button "Big".

To walk up 2 levels, use:

//button[text()="Big"/parent::*/parent::*

And then you could write a loop to add /parent::* to the xpath and then try clicking, until it doesn't throw exception then exit the loop.

Yes, as mentioned in the other answer, you can use xpath. But it is often easier to start from the current node when walking up the dom.

'./parent::*/parent::*/parent::*/parent::*'

The dot and slash ./ in the beginning starts at the current node. So the code above walks up the DOM by 4 levels.

like image 39
Jonathan Avatar answered Oct 26 '25 12:10

Jonathan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!