为什么我会收到有关测试方法的陈旧元素参考?
why am I receiving stale element reference on test method?
我目前正在开发一个使用 java、selenium、selenium-grid、pageObject 和 pageFactory 的自动化框架。
我正在尝试创建一种方法来测试以下 html 代码:
<section class="footer-links">
<div class="footer-layout">
<ul>
<li class="title">Header</li>
<li><a href="/home/">text</a></li>
<li><a href="/about/">text</a></li>
<li><a href="/games/">text</a></li>
<li><a href="/games/download/" >text</a></li>
<li><a href="/games/mobile/" >text</a></li>
<li><a href="/events/" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/publishers/" >text</a></li>
<li><a href="/smth/" target="_blank" >text</a></li>
<li><a href="/promo/press/" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/support/" >text</a></li>
<li><a href="/support/payment-inquiries/" class="loginModalShow" rel="nofollow" >text</a></li>
<li><a href="/support/general-inquiries/" >text</a></li>
<li><a href="/support/game-inquiries/" class="loginModalShow" rel="nofollow" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/blog/" >text</a></li>
<li><a href="/search/" rel="nofollow" >text</a></li>
<li><a href="/directory/pc-games/" >text</a></li>
</ul>
</div>
上面的代码表示包含 4 个列表和一些链接的页脚。
我试图用以下方法做的是遍历 4 个列表一次,然后在每个列表中再次单击链接并验证 url 他们根据 href 属性值重定向到的链接。
@FindBy(css = ".footer-links .footer-layout ul")
public List<WebElement> footerLinksLists;
public void checkFooterLinks(){
if (footerLinksLists.size()==4){
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(driver.getCurrentUrl().contains(href)){
log.info("Link " + href +" is ok");
}
driver.navigate().back();
}
}
}else{
log.info("the footer does not contain 4 link lists");
}
}
开始我的测试后,它在进入 for 循环后中断并出现以下错误
org.openqa.selenium.StaleElementReferenceException: The element reference of <li> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
在我的测试中 class 我有以下代码用于初始化包含方法的页面对象:
WebDriver driver = driverFactory.getDriver();
WebDriverWait wait = driverFactory.getWait(driver);
homepagePageObject homePage = new homepagePageObject(driver, wait);
PageFactory.initElements(driver,homePage);
homePage.createAccount();
homePage.checkVerifyAccountRibbon();
homePage.signOut();
homePage.Login();
homePage.checkFooterLinks();
最初我认为这与等待每个元素有关,但在添加 waits/expectedConditions.
后我收到了同样的错误
谁能解释一下我做错了什么,在这种情况下最好的解决方案是什么?
因为页面刷新并且列表元素失去了它的值。
您必须通过重新分配链接值来管理它。
public void checkFooterLinks(){
if (footerLinksLists.size()==4){
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(driver.getCurrentUrl().contains(href)){
log.info("Link " + href +" is ok");
}
driver.navigate().back();
}
links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"))));
}
}else{
log.info("the footer does not contain 4 link lists");
}
}
此方法未完成您希望它执行的操作。
首先,只有当footerlink的个数为4时,才会经过这个循环。
如果 link 的数量发生了变化,或者有一个错误导致它变成了 3,整个方法就会被跳过,你只会得到一个记录事实的日志语句。
由于没有断言,并且该方法没有 return 任何东西,因此该方法每次都会通过 运行。
其次,如果 link 不包含预期的 href,if 语句将不会执行。这意味着您不会在日志中包含 OK 语句。
该方法仍将执行并成功。
我建议在此测试中包含一些断言。作为每次迭代的一部分。所以像这样:
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
**assertTrue("The expected URL did not match",driver.getCurrentUrl().contains(href));**
driver.navigate().back();
}
或作为方法本身的 return
public boolean checkFooterLinks(){
if (!footerLinksLists.size()==4){
return false;
}
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(!driver.getCurrentUrl().contains(href)){
return false;
}
driver.navigate().back();
}
}
return true;
}
然后让测试验证 link 与
是否正常
assertTrue("something is not right with the footer links",checkFooterLinks())
这给你的是,如果link的个数不是4,或者打开的link不符合预期,测试就会失败。
也就是说,我可以看到检查 link 的价值并且它们包含预期的 href 值,但我不确定检查实际 url 会给你什么价值.
如果 href 已损坏并指向 www.google.com,则测试将通过,因为两个值匹配。仅供参考。
我目前正在开发一个使用 java、selenium、selenium-grid、pageObject 和 pageFactory 的自动化框架。
我正在尝试创建一种方法来测试以下 html 代码:
<section class="footer-links">
<div class="footer-layout">
<ul>
<li class="title">Header</li>
<li><a href="/home/">text</a></li>
<li><a href="/about/">text</a></li>
<li><a href="/games/">text</a></li>
<li><a href="/games/download/" >text</a></li>
<li><a href="/games/mobile/" >text</a></li>
<li><a href="/events/" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/publishers/" >text</a></li>
<li><a href="/smth/" target="_blank" >text</a></li>
<li><a href="/promo/press/" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/support/" >text</a></li>
<li><a href="/support/payment-inquiries/" class="loginModalShow" rel="nofollow" >text</a></li>
<li><a href="/support/general-inquiries/" >text</a></li>
<li><a href="/support/game-inquiries/" class="loginModalShow" rel="nofollow" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/blog/" >text</a></li>
<li><a href="/search/" rel="nofollow" >text</a></li>
<li><a href="/directory/pc-games/" >text</a></li>
</ul>
</div>
上面的代码表示包含 4 个列表和一些链接的页脚。
我试图用以下方法做的是遍历 4 个列表一次,然后在每个列表中再次单击链接并验证 url 他们根据 href 属性值重定向到的链接。
@FindBy(css = ".footer-links .footer-layout ul")
public List<WebElement> footerLinksLists;
public void checkFooterLinks(){
if (footerLinksLists.size()==4){
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(driver.getCurrentUrl().contains(href)){
log.info("Link " + href +" is ok");
}
driver.navigate().back();
}
}
}else{
log.info("the footer does not contain 4 link lists");
}
}
开始我的测试后,它在进入 for 循环后中断并出现以下错误
org.openqa.selenium.StaleElementReferenceException: The element reference of <li> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
在我的测试中 class 我有以下代码用于初始化包含方法的页面对象:
WebDriver driver = driverFactory.getDriver();
WebDriverWait wait = driverFactory.getWait(driver);
homepagePageObject homePage = new homepagePageObject(driver, wait);
PageFactory.initElements(driver,homePage);
homePage.createAccount();
homePage.checkVerifyAccountRibbon();
homePage.signOut();
homePage.Login();
homePage.checkFooterLinks();
最初我认为这与等待每个元素有关,但在添加 waits/expectedConditions.
后我收到了同样的错误谁能解释一下我做错了什么,在这种情况下最好的解决方案是什么?
因为页面刷新并且列表元素失去了它的值。
您必须通过重新分配链接值来管理它。
public void checkFooterLinks(){
if (footerLinksLists.size()==4){
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(driver.getCurrentUrl().contains(href)){
log.info("Link " + href +" is ok");
}
driver.navigate().back();
}
links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"))));
}
}else{
log.info("the footer does not contain 4 link lists");
}
}
此方法未完成您希望它执行的操作。
首先,只有当footerlink的个数为4时,才会经过这个循环。 如果 link 的数量发生了变化,或者有一个错误导致它变成了 3,整个方法就会被跳过,你只会得到一个记录事实的日志语句。 由于没有断言,并且该方法没有 return 任何东西,因此该方法每次都会通过 运行。
其次,如果 link 不包含预期的 href,if 语句将不会执行。这意味着您不会在日志中包含 OK 语句。 该方法仍将执行并成功。
我建议在此测试中包含一些断言。作为每次迭代的一部分。所以像这样:
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
**assertTrue("The expected URL did not match",driver.getCurrentUrl().contains(href));**
driver.navigate().back();
}
或作为方法本身的 return
public boolean checkFooterLinks(){
if (!footerLinksLists.size()==4){
return false;
}
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(!driver.getCurrentUrl().contains(href)){
return false;
}
driver.navigate().back();
}
}
return true;
}
然后让测试验证 link 与
是否正常assertTrue("something is not right with the footer links",checkFooterLinks())
这给你的是,如果link的个数不是4,或者打开的link不符合预期,测试就会失败。
也就是说,我可以看到检查 link 的价值并且它们包含预期的 href 值,但我不确定检查实际 url 会给你什么价值.
如果 href 已损坏并指向 www.google.com,则测试将通过,因为两个值匹配。仅供参考。