再次回到另一个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
或某些逻辑,则会返回错误。
答案 0 :(得分:1)
在两种情况之一中抛出过时的元素引用异常, 第一个比第二个更常见:
该元素已被完全删除。该元素不再存在 附在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}}。祝你好运。