¿Have you ever mapped an element in your page object, it runs awesome the first time and then… Does it just stop finding the element out of a sudden? This can happen for a bunch of reasons. One of these reasons could be that the element you’re trying to map, is dynamic.
By Dynamic, I mean that the element’s locator changes every time the page is loaded. Developers do this for several reasons that can inspire a whole other article.
Let’s take as an example one element of this blog. If you go to the HomePage and inspect the posts that show up, you’ll notice the IDs are something like “post-XXX” and they don’t show a clear numerical pattern. If we made a script that mapped “post-294” exactly, there is a chance that in the future this element could give us problems.
But what can we do to solve this?
There are several ways of tackling this issue. We’ll cover the most common ones:
Find alternative ways of locating the dynamic element
Now we’ll dive into our first solution. If one method of locating the element (using its ID directly) doesn’t work, try another one! Selenium offers a huge array of methods to locate an element. Chances are, you’ll find another one that better suits your needs.
Let’s take a deeper look at our element:
Here we can see that we have a <article> that’s inside a <main> that’s inside an <div> each of them with a seemingly unique ID. This means we could use a relative Xpath or CSS Selector to get to the dynamic element we want.
An Xpath like this one:
| //div/main/article[1]
Or a CSS Selector like this one:
| div>main>article:first-of-type
Would be sufficient to accomplish what we want. But what if we are not so lucky and don’t have a similar structure in our HTML that allows us to do this? Well, then we would need to look even deeper.
Look at the dynamic element attributes
If we take another look at our <article>, we’ll notice that it has quite a bunch of classes assigned to it. Maybe one of those classes is unique and can help us achieve our goal.
For example:
| post = self.driver.find_element((By.CLASS_NAME, “blog-post”)
If we use the default find_element method provided by Selenium, it will return the first element found that meets the specified criteria. Which in this case, is exactly what we want. But then again, what happens if the dynamic element we’re looking for also doesn’t have a unique class we can use to find it?
Well, that’s when we pull out the big guns
That’s when we go to our last resort. Use an XPath that selects the dynamic element based on the part of the ID that doesn’t change.
| //article[contains(@id, ‘post-‘)][1]
In this XPath, we’re selecting the first <article> whose ID contains “post-“.
This said, we can also combine a few of these tips depending on how specific we want to be with our locator, but keep in mind that the more specific the locator is, the more brittle it becomes.
This article was written by Mike Arias
Senior Software Testing Engineer of TechAID.
Twitter: @theqaboy
Blog: qaboy.com/