Selenium使用WebElement列表报Stale Element 单独元素操作正常
问题解决:预存WebElement触发StaleElementReferenceException异常
核心原因
StaleElementReferenceException触发的根本逻辑是:你提前将所有星标元素查找后存入List的操作完成后,页面DOM发生了更新(可能是悬停操作触发了星标组件的重绘逻辑,哪怕视觉上无变化,底层DOM节点已被替换),你提前缓存的WebElement对象引用直接失效,因此哪怕对应XPath完全正确,也无法通过旧引用操作元素。
你单独操作单个元素可以正常执行,是因为单次查找+操作的过程中,DOM没有发生更新,引用始终有效。
修复方案
不要预加载所有WebElement存入List,改为每次执行悬停操作前,实时通过索引查找对应元素即可,修改后代码如下:
System.out.println("=====================All star start ================"); Actions actions= new Actions(driver); // 不需要提前存储WebElement,直接按索引循环操作即可 Reporter.log("Started hovering star elements", true); for(int i=11,j=22;i<=15;i++,j=j+2) { Reporter.log("Started hovering index: "+i, true); // 每次操作前实时查找元素 WebElement currentStar = driver.findElement(By.xpath("(//*[name()='svg'][@class='rvs-star-svg'])["+i+"]")); actions.moveToElement(currentStar).build().perform(); Thread.sleep(2000); // 如果需要取path属性也实时查找 WebElement currentStarPath = driver.findElement(By.xpath("(//*[name()='svg']//*[name()='path'])["+j+"]")); System.out.println("Star"+(i-10)+"has color "+currentStarPath.getAttribute("stroke")); }
可选优化方案
如果有多次操作元素的需求,也可以提前把对应元素的XPath表达式存入List,后续所有操作都从XPath实时查找元素,避免缓存引用失效:
// 提前存XPath而非WebElement List<String> starXpathList = new ArrayList<>(); List<String> starColorXpathList = new ArrayList<>(); for(int i=11,j=22;i<=15;i++,j=j+2) { starXpathList.add("(//*[name()='svg'][@class='rvs-star-svg'])["+i+"]"); starColorXpathList.add("(//*[name()='svg']//*[name()='path'])["+j+"]"); } // 后续操作时实时查找 Actions actions= new Actions(driver); for(int i=0;i<starXpathList.size();i++){ WebElement star = driver.findElement(By.xpath(starXpathList.get(i))); actions.moveToElement(star).build().perform(); Thread.sleep(2000); WebElement starPath = driver.findElement(By.xpath(starColorXpathList.get(i))); System.out.println("Star"+i+"has color "+starPath.getAttribute("stroke")); }
内容的提问来源于stack exchange,提问作者sanket negi
相关产品推荐
相关产品推荐

