为什么我会收到有关测试方法的陈旧元素引用?

时间:2018-09-05 13:17:18

标签: java selenium selenium-webdriver pageobjects

我目前正在使用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个列表,然后在每个列表中再次单击链接,并根据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

在测试类中,我有以下代码用于初始化包含该方法的pageobject:

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之后,我收到相同的错误。

有人可以解释我在做什么错,在这种情况下最好的解决方案是什么?

2 个答案:

答案 0 :(得分:1)

因为页面刷新,并且List元素的值丢失。

您必须通过重新分配链接值来对其进行管理。

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");
    }
}

答案 1 :(得分:0)

此方法无法执行您想要的操作。

首先,仅当脚注链接数为4时,它才会通过此循环。 如果更改了链接数,或者存在导致该链接数为3的错误,那么将跳过整个方法,您只需要获取一条事实的日志语句即可。 由于没有断言,并且该方法不返回任何内容,因此该方法将在每次运行时通过。

第二,如果链接不包含预期的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();
        }

或从方法本身返回

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;

}

,然后让测试验证链接是否正确

assertTrue("something is not right with the footer links",checkFooterLinks())

这为您提供的是,如果链接数不是4,或者打开的链接与预期的不符,则测试将失败。

也就是说,我可以看到检查链接的值,并且它们包含预期的href值,但是我不确定检查实际URL会为您提供什么值。

如果href损坏并指向www.google.com,则两个值匹配时测试将通过。值得深思。