元素存在失败的硒测试

时间:2015-07-14 20:23:36

标签: java selenium selenium-webdriver

再次回到另一个Selenium问题!...

这是我到目前为止所拥有的

dynamic_cast

由于某种原因,在我知道的页面上应该返回一个空列表(因为不应该找到页面标题),我不断得到的两个例外是“StaleElementReferenceException”(或类似的东西)或“元素是不再附加到DOM“。有没有更好的方法来解决这个问题?

我试图通过为需要的每个页面调用自己来使方法动态化;遗憾的是,Selenium方法不会使这方便,因为如果他们找不到元素而不是public static void mobileAssessmentPage() { List<WebElement> elements = SeleniumCommands.findElementsByCss(ASSESSMENTANSWER); List<WebElement> pageTitle; for (WebElement element : elements) element.click(); SeleniumCommands.waitClickById(ASSESSMENTNEXTPAGEBUTTON); try { Thread.sleep(500); } catch (InterruptedException ie) { ie.getMessage(); } pageTitle = SeleniumCommands.findElementsByXpath(PAGETITLE); try { Thread.sleep(500); } catch (InterruptedException ie) { ie.getMessage(); } System.out.println(pageTitle.get(0)); if (pageTitle.size() > 0) { if (pageTitle.get(0).getText().equals("Assessment")) mobileAssessmentPage(); } } Boolean或甚至-1或某些逻辑,则会返回错误。

2 个答案:

答案 0 :(得分:1)

来自selenium docs

  

在两种情况之一中抛出过时的元素引用异常,   第一个比第二个更常见:

     

该元素已被完全删除。该元素不再存在   附在DOM上。

后者包括删除元素并由具有几乎相同属性和DOM位置的新元素替换的情况。任何JS库都可能这样做是为了响应单击其中一个元素,因此其余元素变得“陈旧”。

你怎么能避免这种情况?

我使用的一个解决方案是不保留对每个元素的引用,而是在单击之前找到每个元素。由于元素共享一个选择器,您可以先获取计数,然后通过子索引获取它们。调整你的例子:

public static void mobileAssessmentPage() {
    int q = SeleniumCommands.findElementsByCss(ASSESSMENTANSWER).count();

    List<WebElement> pageTitle;

    for (int i = 0; i < q; i++) {
        WebElement element = SeleniumCommands.findElementsByCss(ASSESSMENTANSWER)[i];
        element.click();
    }

    SeleniumCommands.waitClickById(ASSESSMENTNEXTPAGEBUTTON);
    try { Thread.sleep(500); } catch (InterruptedException ie) { ie.getMessage(); }
    pageTitle = SeleniumCommands.findElementsByXpath(PAGETITLE);
    try { Thread.sleep(500); } catch (InterruptedException ie) { ie.getMessage(); }
    System.out.println(pageTitle.get(0));
    if (pageTitle.size() > 0)
        if (pageTitle.get(0).getText().equals("Assessment"))
            mobileAssessmentPage();
}

如果这还不够(很多时候不是这样),你可能想在for中使用一些等待或重试,例如:

    for (int i = 0; i < q; i++) {            
        WebElement element = SeleniumCommands.findElementsByCss(ASSESSMENTANSWER)[i];
        element.click();
        Thread.sleep(200);
    }

或:

    for (int i = 0; i < q; i++) {            
        try {
            WebElement element = SeleniumCommands.findElementsByCss(ASSESSMENTANSWER)[i];
            element.click();
        } catch (StaleElementReferenceException e) {
            Thread.sleep(200); // optional, but just to be safe...
            WebElement element = SeleniumCommands.findElementsByCss(ASSESSMENTANSWER)[i];
            element.click();
        }            
    }

答案 1 :(得分:1)

首先你不应该使用Thread sleep!这是生产测试的不良做法。您还应该使用页面对象模式(它非常有用)。

关于您的实际问题:元素需要一些时间才能附加到父元素。例如:当开发人员使用动画或应用程序生成困难的用户界面时,此过程需要一些时间进行渲染。否则,只要应用程序完成某些任务,就会附加该元素。你只需要等待元素附加。 Webdriver为这种情况提供了特殊的类和方法:

 WebElement webElement = new WebDriverWait(driver(), 3).until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("some css celector"))); //this code wait untill element will be attached about 3 seconds
webElement.click() //now you clicking on element

您可以在ExpectedConditions课程中使用许多有用的方法。请记住,您应该很少使用Thread.sleep(),并且只有在您没有其他选项时才使用{{1}}。祝你好运。