You’ve just written a test using the WebDriver framework and you’re confident that it’s complete. You go to test it and….it fails with the dreaded stale element reference error. What’s Your Move?
According to MDN, the official Mozilla website for development documentation of web standards, the error occurs because you are trying to perform an action to a web element that references an element that is no longer attached to the DOM.
A variety of scenarios can trigger this behavior from the web page. It’s not expected to be in the page, so it’s best practice to avoid trying to perform an action with that web element. However, there are events that can trigger the replacement of an element, resulting in the web element representing it to become stale. The latter is the scenario we will be discussing.
If you’re anything like me when you face an error, you’ll turn to the internet for help. A quick search will tell you to solve this issue by retrying in a loop. Not a great fix, but QA engineers will still use it because, well, it works. However, I caution you to be aware of the potential pitfalls associated with this approach. The loop can be infinite depending on the implementation. This can be easily solved by establishing a limit, but this approach still isn’t scalable. It would require you to duplicate a lot of code that includes a loop and a try catch block.
Now, we have an issue that cannot be solved as easily.
You may notice the potential pitfalls mentioned above. For one, it may loop indefinitely because there is no control in case the element is forever stale. And, we’ll still need to repeat this code for additional actions like .GetAttribute, .IsEnabled, .Text which will create our scalability issue.
If you go back to the definition of stale element reference error in MDN, you will notice it mentions a UUID, which the WebDriver uses to identify each element it fetches. This UUID changes whenever an element changes. When an element goes from not stale to stale back to not stale again, change is happening, right? Understanding this is crucial in the development of a more scalable solution to avoiding the stale element reference error.
First, you will need to make sure you have access to that UUID in the framework you are using. In Selenium.NET, it is available through the ToString() method of the IWebElement interface. Then, you must find out which action triggers the replacement of the element you are trying to interact with. This step is critical because it defines a before and after and it will help you understand the application better, which is a win for you as part of the QA team. Now that you have identified the turning point, save the UUID of the element before that command.
Finally, you must find a way to limit the evaluation of this UUID. You can choose to limit by amount of iterations or time. Since the changes of the element happen over time, maybe time is the best way to go. In Selenium.NET, the WebDriverWait class will help since you can specify a timeout limit.
This solves both our pitfalls because it has a limit and a timeout exception. After the implementation of these lines, you are safe to interact with the element. Is it perfect? Maybe not, there still may be some scalability issues, but most of those can be easily addressed regardless of your architecture.
Derick Arzu is a Software Engineer at number8 with extensive experience in QA Automation. He is knowledgeable in Selenium WebDriver, WebdriverIO, Protractor.js, NUnit, Mocha.js, Cucumber.js, and Chai.js. You can keep up with him by following his blog at https://derickarzu.dev/
Provide your information to talk with a number8 Account Executive about your development needs today and feel what it’s like to be listened to before being sold a solution.
Let us help you add highly skilled, versatile developers to your team.