【问题标题】:why am I receiving stale element reference on test method?为什么我会收到有关测试方法的陈旧元素参考?
【发布时间】:2018-09-05 13:17:17
【问题描述】:

我目前正在开发一个使用 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 属性值验证它们重定向到的 url。

@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

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

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();

最初我认为这与等待每个元素有关,但在添加等待/预期条件后我收到相同的错误。

谁能解释我做错了什么以及在这种情况下最好的解决方案是什么?

【问题讨论】:

    标签: java selenium selenium-webdriver pageobjects


    【解决方案1】:

    因为页面刷新,列表元素失去了它的价值。

    你必须通过重新分配链接值来管理它。

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

    【讨论】:

    • 是否应该在for循环导航链接内完成重新分配链接?
    • @samabcde 我没找到你。
    • 我只是怀疑如果导航到其他页面会使 WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));失败,如果没有,请纠正我。
    • @samabcde 在我按照建议将重新分配链接移动到另一个 for 循环中之后,它起作用了。谢谢大家(:
    【解决方案2】:

    这个方法没有做你想做的事。

    首先,只有在页脚链接数为 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,则测试将在两个值匹配时通过。值得深思。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多