Hello Folks,
This is on demand post. Many people asked me how to handle StaleElementReferenceException through Page Object Model(POM) – PageFactory. So thought of writing a simple post on it.
I am trying to automate below steps:
- Load URL “https://github.com/login”.
- Type wrong username.
- Type wrong password.
- Click on submit.
- Type correct username.
- Type correct password.
- Click on submit.
Run the below program:
1
|
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class StaleElementHandling {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
WebDriver driver= new ChromeDriver();
// Open URL
driver.get("https://github.com/login");
// locate and type username
WebElement username= driver.findElement(By.id("login_field"));
username.sendKeys("amod");
// locate and type password
WebElement pass= driver.findElement(By.id("password"));
pass.sendKeys("amod");
// locate and click on submit
WebElement sub= driver.findElement(By.xpath("//input[@value='Sign in']"));
sub.click();
Thread.sleep(10000);
// again type username
username.sendKeys("amod");
}
}
|
Output:
We get StaleElementReferenceException at line
username.sendKeys(“amod”);
What is StaleElementReferenceException and when it occurs?
Indicates that a reference to an element is now “stale” or the element no longer appears on the DOM of the page. Let’s understand this with real time example:-
You stay on a rented house in Silk board. All bank statements, documents are sent to your Silk board address. After some time you shift to BTM from Silk board. All documents sent to your Silk board address will be returned back as you do not stay there any more. You need to update latest address everywhere so that you will get all documents at your new address BTM.
In above example, we typed username, password and clicked on submit button. Page reloads and shows you error message “Incorrect username or password.” with login page as previous. Same page is shown again but address is changed. Address is referred as reference in JAVA. We are trying to use old reference and getting StaleElementReferenceException.
This is a major exception and you will face it always if you do not follow Page Object Model.
How Page Object Model solves StaleElementReferenceException?
Create two java classes as below:
LoginPage.java
1
|
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
WebDriver driver;
@FindBy(id="login_field")
public WebElement username;
@FindBy(id="password")
public WebElement password;
@FindBy(xpath="//input[@value='Sign in']")
public WebElement submit;
public LoginPage(WebDriver driver)
{
this.driver=driver;
PageFactory.initElements(driver, this);
}
}
|
StaleElementHandling2.java
1
|
import org.openqa.selenium.By;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class StaleElementHandling2 {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
WebDriver driver= new ChromeDriver();
driver.get("https://github.com/login");
LoginPage lp= new LoginPage(driver);
lp.username.sendKeys("amod");
lp.password.sendKeys("dsds");
lp.submit.click();
Thread.sleep(5000);
lp.username.sendKeys("amod");
lp.password.sendKeys("dsds");
lp.submit.click();
}
}
|
You will see programs run fine when we use page object design pattern. You will never get Stale Element Reference Exception. When we use FindBy annotation in POM, webdriver locates element and update reference every time before performing any action on that. You can use web element without relocating any where. This is major advantage of using Page Object Model.
That’s it. Hope, it might be useful for people who face stale exception. If you have any doubt, feel free to comment.
If you like my posts, please like, share, comment and subscribe.
#HappyLearning
Author: Amod Mahajan
My name is Amod Mahajan and I am an IT employee with 6+ years of experience in Software testing and staying in Bengaluru. My area of interest is Automation testing. I started from basics and went through so many selenium tutorials. Thanks to Mukesh Otwani as his tutorials are easy and cover basics to advance. I have habit of exploring concepts by deep diving. I used to make notes. I thought of sharing my knowledge through posts and now I am here. #KeepLearning #ShareLearning
Very well explained.. Thanks.. 🙂
Hi Amod,
When I launch browser and navianav to my application I will click on one link which will redirect to a next page. This operation we are doing in each and every test case. But after some 10 to 15 test cases I am getting StaleElementReference Exception even though there is no page refresh (the element which we are clicking is the first element on the webpage) and we are laughing browser for each and every test case. And even though page is getting loaded completely it’s unable to get an element.
Could you please let me know the cause of issue and how can I resolve it as it’s affecting our nightly batch run. And one more our system is also not going to sleeping mode, it will be active only.
Thanks in advance, waiting for your response.
Hello,
Are you using PageFactory concept? If not, implement it.
But you may get StaleElementReference even after using PageFactory. Suppose you click on a link, you dont see page is being refreshed but some ajax calls happen. If WebDriver finds any element in between that and stores it, that reference will go stale when ajax calls are completed. You can use javascript to get page loading status as completed or proper wait.
Thanks
Amod
We are using PageFactory… Thanks for your suggestion I will try with JavaScript.
Even I am getting Stale Element Reference Exception on Page Object Model.
Yes you can get if webdriver searches for element before page is completely loaded or ajax call is in progress or dynamic application. Page object model says webdriver to locate element if page is refreshed but not smart enough to know when should actually start locating. SO its your responsibility to use proper waits as well.
Very well explained. 🙂
findelements used inside forloop and click part is moved out of these for loops, thanks
Yes, while loop was creating problem.
Issue is solved through code by changing while loop to for loop and adding another for loop inside and using find elements along with counter variable,
hi Amod, could you please suggest the solution pls..its bit urgent
We need to debug it to know actually where it is getting null.
Hi Amod ,
I am facing issue with staleelement issue from 5days, can u suggest how to update in my code https://stackoverflow.com/questions/44471715/element-not-found-in-cache-perhaps-the-page-has-changed-since-it-has-lookedup-s/44476374#44476374
Pls help
Zareena
Try to do a findElement each time before you use the element. i.e put the line
java.util.List ListPath1 = driver.findElements(By.xpath((ReadPropertyFile.readProperty(“ClickNamePath”))));
inside the for loop. What is happening as Amod explained above that address of elements get updated. So if you put the findElements line inside the for loop you will have the latest address and it may solve the problem
give it a try
Hello,
Yours is not exactly stale exception. You have used click in a loop. Once it clicks and den go back to loop. Click changes tha page. This is causing issue.
Awesome explanation Amod…
Thanks Sanjay.
Thanks Amod for explaing the reason behind this exception with a very nice example
So we need to search the element again on the page to get the correct addres..
Instead of using @Findy notation and Pagefactory….
Cant we just put a simple find element like done on this page below…
http://toolsqa.com/selenium-webdriver/page-object-model/
public static WebElement username(WebDriver driver){
element = driver.findElement(By.id(“username”));
return element;
}
is there a difference between the one used by you where we used FindBy and Pagefactory compared to this one where we just do a findElement in the Pageobject class so each time you refer to the element it will be searched again so always correct address would be returned
Thanks Gaurav.
Awesome Amod Bhai…
Thanks Kamaraju.
Thanks Amod. This was much needed article. And once again your simple and easy explanation has cleared all doubts regarding this exception very well. Awesome
Thanks Nidhi.