GVKun编程网logo

Selenium:遍历一组元素时如何避免StaleElementReferenceException?(selenium遍历子元素)

8

本文将为您提供关于Selenium:遍历一组元素时如何避免StaleElementReferenceException?的详细介绍,我们还将为您解释selenium遍历子元素的相关知识,同时,我们还将

本文将为您提供关于Selenium:遍历一组元素时如何避免StaleElementReferenceException?的详细介绍,我们还将为您解释selenium遍历子元素的相关知识,同时,我们还将为您提供关于frameToBeAvailableAndSwitchToIt 之后的 Selenium StaleElementReferenceException、How to avoid “StaleElementReferenceException” in Selenium?、java+selenium报异常org.openqa.selenium.StaleElementReferenceException的解决方案、org.openqa.selenium.ElementNotSelectableException的实例源码的实用信息。

本文目录一览:

Selenium:遍历一组元素时如何避免StaleElementReferenceException?(selenium遍历子元素)

Selenium:遍历一组元素时如何避免StaleElementReferenceException?(selenium遍历子元素)

我的页面包含一堆表格。我在外循环中遍历表,然后在内循环中遍历表中的每一行。一切正常。但是某些页面具有“下一步”按钮。当我在完成页面后添加代码以单击该代码时,则在遍历表的各行时开始获取StaleElementReferenceException。

这是代码:

WebDriverWait wait1 = new WebDriverWait(driver, 10000);WebElement maxPage = null;WebElement auctionsWaitingDiv = driver.findElement(By.cssSelector("div[Head_W'']"));if (auctionsWaitingDiv.isDisplayed() == false) return properties;try {    maxPage = wait1.until(ExpectedConditions.visibilityOfElementLocated(By.id("maxWA")));} catch (TimeoutException ex) {    return properties;}Integer maxPageNo = 1;if (!maxPage.getText().isEmpty())     maxPageNo = Integer.parseInt(maxPage.getText());for (int i = 1; i <= maxPageNo; i++) {    driver.findElement(By.cssSelector("div[id=''Area_W'']"));    //only look at Auctions Waiting section    WebDriverWait wait2 = new WebDriverWait(driver, 10000);    List<WebElement> tables = null;    try {        tables = wait2.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("table[ad_tab'']")));    } catch (TimeoutException ex) {        System.out.println("table not found in allotted time");        return properties;    } catch (StaleElementReferenceException ex) {        System.out.println("returning due to StaleElementReferenceException");        return properties;    }    for (WebElement table: tables) {          List<String> propAttributes = new ArrayList<>();        // StaleElementReferenceException: The element reference of        // <table> 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        List<WebElement> rows = table.findElements(By.cssSelector("tr"));        String parcelLink = "";        for (WebElement row : rows) {             WebElement key = row.findElement(By.cssSelector("th"));            WebElement val = row.findElement(By.cssSelector("td"));            String keyVal = key.getText() + val.getText();            propAttributes.add(keyVal);            if (key.getText().equals("Parcel ID:")) {                WebElement a = val.findElement(By.cssSelector("a"));                parcelLink = a.getAttribute("href");            }        }    }    driver.findElement(By.xpath(".//*[@PageRight'']")).click();  //click the "Next" button}

我不明白的是,为什么过时的因素根本没有发生?该页面在循环过程中没有更改,我一直等到所有元素都提取完之后。如何避免StaleElementReferenceException?

编辑:最后的堆栈跟踪显示它发生在此行中:

List<WebElement> rows = table.findElements(By.cssSelector("tr"));

上面的错误消息显示:

严重:null

org.openqa.selenium.StaleElementReferenceException:的元素引用<table>是陈旧的;元素不再附加到DOM,不在当前框架上下文中,或者文档已刷新

答案1

小编典典

在将头发梳理了一天之后,我终于意识到发生了什么。对我来说应该是显而易见的。单击“下一步”按钮时,加载新页面需要一些时间。通过简单地添加一个延迟,就可以加载新的DOM并开始对其进行处理,而不是对前一个DOM进行处理!

            driver.findElement(By.xpath(".//*[@PageRight'']")).click();        try {            Thread.sleep(4000); //provide some time for the page to load before processing it        } catch (InterruptedException ex) {            Logger.getLogger(RealAuction.class.getName()).log(Level.SEVERE, null, ex);        }

现在,它可以运行到没有StaleElementReferenceException的状态。

frameToBeAvailableAndSwitchToIt 之后的 Selenium StaleElementReferenceException

frameToBeAvailableAndSwitchToIt 之后的 Selenium StaleElementReferenceException

代替那些较小的冗余步骤,您可以切换到所需的 <iframe> 诱导 WebDriverWait 使用 xpath 优化如下:

new WebDriverWait(driver,10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("xpIframe")));

参考

您可以在以下位置找到一些相关讨论:

  • Ways to deal with #document under iframe
  • Is it possible to switch to an element in a frame without using driver.switchTo().frame(“frameName”) in Selenium Webdriver Java?
,

第 3 行

wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath(xpIframe)));

您已经切换到 iframe。所以不需要第 4 行——它只是尝试切换到同一帧。尽量去掉(第2行也是多余的)

How to avoid “StaleElementReferenceException” in Selenium?

How to avoid “StaleElementReferenceException” in Selenium?

我正在使用Java实现许多Selenium测试。有时,我的测试由于导致失败StaleElementReferenceException。你能否提出一些使测试更稳定的方法?

答案1

小编典典

如果页面上发生的DOM操作暂时导致该元素不可访问,则会发生这种情况。为了允许这些情况,您可以尝试在最终引发异常之前循环访问几次元素。

试试darrelgrainger.blogspot.com的出色解决方案:

public boolean retryingFindClick(By by) {    boolean result = false;    int attempts = 0;    while(attempts < 2) {        try {            driver.findElement(by).click();            result = true;            break;        } catch(StaleElementException e) {        }        attempts++;    }    return result;}

java+selenium报异常org.openqa.selenium.StaleElementReferenceException的解决方案

java+selenium报异常org.openqa.selenium.StaleElementReferenceException的解决方案

因为页面内容有很多页,需要切换页数,但是切换跳转到第二页的时候,页面首先会自动刷新,导致出现如下异常:Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document

	//获取当前页面的table内容
	static int count = 0;
	public static List getPageTableContent(WebDriver driver,WebElement table,String refreshElement ){
		
		//获取当前页面的table
//把下面这行代码的注释去掉即可
//		table= driver.findElement(By.xpath(refreshElement));
		
		List<WebElement> rows = table.findElements(By.tagName("tr"));//根据行标签,获取所有行对象
		//String[] tableTitle = {"编号","配置名称","首页返回按钮","首页banner显示","极简尾页",""};
		ArrayList<String> tableContent = new ArrayList<>();
		for(WebElement row:rows){//从所有行中遍历每一行
			List<WebElement> col = row.findElements(By.tagName("td"));//一行中,所有列标签,
			for(WebElement cell:col){//一行中,所有的列(也就是单元格)
				String content = cell.getText();//每个单元格的内容
				tableContent.add(content);
				//System.out.println(content + "...content");
				//System.out.println(driver.findElement(By.xpath("//td[contains(text(),''可以'')]")).getText() + "...findElement");
				
			}
		}
		return tableContent;
	}
	
	//获取总页数
	public static int getPageAllNo(WebDriver driver){
		//获取总页数
				String pageCountSumStr = driver.findElement(
						By.xpath("//*[@id=''product_mgt_wrap'']/div/div[2]/div[3]/table/tbody/tr/td[8]/span")).getText();
				int pageCountSum = Integer.parseInt(pageCountSumStr.substring(3));
				return pageCountSum;
	}
	
	//获取当前页数
	public static int getCurrentPageNo(WebDriver driver){
		String pageCountSumStr = driver.findElement(
				By.xpath("//*[@id=''product_mgt_wrap'']/div/div[2]/div[3]/table/tbody/tr/td[8]/span")).getText();
		//获取当前页面页数
				String pageSource = driver.getPageSource();//获取当前页的源文件
				String pageElement = "pagination-num\" type=\"text\" value=\"";//在源文件中查找含有该字段的位置
				int pageIndex = pageSource.indexOf(pageElement);//通过上面的字段位置,定位文本框中的当前页数
				//通过定位出来的位置,获取文本框中的值 
	}
	//根据表格单元个内容定位单元格所在行
	/**
	 * @author:苏一叶 email:by.su@qq.com
	 * 1.进来先获取页面的总页数
	 * 2.如果总页数大于1
	 * 3.把每一条记录所有字段和记录所在的当前页数存入json中,表头为Key,值为Value。
	 * #3.把每一条记录中除编号外的其他字段和记录所在的当前页数存入json中,编号作为Key,其他已经存入json作为Value存入HashMap中。
	 * 4.传入需要定位的字符串,根据字符在json中查找对应的页数,把所有含有该字符的记录存到
	 * @throws InterruptedException 
	 */
	public static void getRangeFromRows(WebDriver driver,String str) throws InterruptedException{
		int pageCountSum = getPageAllNo(driver);//获取总页数
		int currentPageCount = getCurrentPageNo(driver);//获取当前页数
		
		//需要定位元素的xpath
		String strContent = "//*[contains(text(),''" + str + "'')]";
		//获取当前页面的table
        String refreshElement = "//*[@id=''product_mgt_wrap'']/div[1]/div[2]/div[2]/div[2]/div[2]/table";
		WebElement table= driver.findElement(By.xpath(refreshElement));
		                                              
		if(pageCountSum == 1){
			ArrayList<String> tableContent = (ArrayList)getPageTableContent(driver,table,refreshElement);
			for(String content:tableContent){
				if(content.contains(str)){//若包含需要查找定位的关键字str
					driver.findElement(By.xpath(strContent)).click();
				}
			}
			
		}else{//页面总数大于1的时候
			boolean flag = false;//设置一个跳出的标志位
			for(int i=0;i<pageCountSum&&!flag;i++){
				//当前页面等于1的时候
				if(currentPageCount==1){
					ArrayList<String> tableContent = (ArrayList)getPageTableContent(driver,table,refreshElement);
					
					for(String content:tableContent){
						if(content.contains(str)){//若包含需要查找定位的关键字str
							driver.findElement(By.xpath(strContent)).click();
							flag = true;//若找到,即跳转出循环
							break;//退出该循环体
						}
					}
					Thread.sleep(1000);
					currentPageCount += 1;//设置页数为2,页数大于1,逻辑转到else下面的代码块
				}else{
					//点击下一页的按钮,页面跳转到下一页,从第1页跳转到第2页
					driver.findElement(By.xpath("//*[@id=''product_mgt_wrap'']/div/div[2]/div[3]/table/tbody/tr/td[10]/a/span/span[2]")).click();
					Thread.sleep(1500);
					//从第2页开始,每翻一页,都进行查找定位
					for(int n=2;n<=pageCountSum&&!flag;n++){
						ArrayList<String> tableContent = (ArrayList)getPageTableContent(driver,table);
						//点击下一页按钮
						driver.findElement(By.xpath("//*[@id=''product_mgt_wrap'']/div/div[2]/div[3]/table/tbody/tr/td[10]/a/span/span[2]")).click();
						Thread.sleep(1000);
						currentPageCount = getCurrentPageNo(driver);//获取跳转后的页数
						
						for(String content:tableContent){
							if(content.contains(str)){//若包含需要查找定位的关键字str
								driver.findElement(By.xpath(strContent)).click();
								flag = true;//找到定位跳转到flag标志位
							}
						}
						/*//获取所有页面的内容
						tableContentAll.addAll((ArrayList)getPageTableContent(driver,table,refreshElement));*/
					}
				}
			}
			Thread.sleep(1000);
		}
	}

参考自:

http://www.cnblogs.com/fengpingfan/p/4583325.html

http://stackoverflow.com/questions/28066135/org-openqa-selenium-staleelementreferenceexception-stale-element-reference-ele

org.openqa.selenium.ElementNotSelectableException的实例源码

org.openqa.selenium.ElementNotSelectableException的实例源码

项目:bromium    文件:ClickClassByText.java   
@Override
public void executeAfterJSPreconditionHasBeenSatisfied(WebDriver driver,ReplayingState state) {
    By elementsLocator = By.className(initialCollectorClass);
    List<WebElement> webElements = driver.findElements(elementsLocator);

    Optional<WebElement> webElementOptional = webElements.stream()
            .filter(this::elementTextIsEqualToAndisdisplayed)
            .findFirst();

    if (!webElementOptional.isPresent()) {
        throw new ElementNotSelectableException("Element with class "
                + initialCollectorClass
                + " and text " + text + " was not found" );
    }

    webElementOptional.get().click();
}
项目:bromium    文件:ClickClassByTextTest.java   
@Test
public void throwsExceptionIfNoSuitableElementsAreFound() {
    WebElement incorrectWebElement = mock(WebElement.class);
    when(incorrectWebElement.getAttribute(INNER_HTML)).thenReturn("soMetaTPhing");
    when(incorrectWebElement.isdisplayed()).thenReturn(true);

    List<WebElement> webElements = new ArrayList<>();
    webElements.add(incorrectWebElement);

    By elementsLocator = By.className(initialCollectorClass);
    WebDriver webDriver = mock(WebDriver.class);
    when(webDriver.findElements(elementsLocator)).thenReturn(webElements);

    ClickClassByText clickClassByText = new ClickClassByText(initialCollectorClass,text,eventName,expectsHttp);
    thrown.expect(ElementNotSelectableException.class);
    clickClassByText.executeAfterJSPreconditionHasBeenSatisfied(webDriver,mock(ReplayingState.class));
}
项目:alex    文件:AlertSendKeysAction.java   
@Override
protected ExecuteResult execute(final WebSiteConnector connector) {
    try {
        final Alert alert = connector.getDriver().switchTo().alert();
        alert.sendKeys(insertvariableValues(text));

        LOGGER.info(LEARNER_MARKER,"Send text '{}' to prompt window (ignoreFailure: {},negated: {}).",ignoreFailure,negated);

        return getSuccessOutput();
    } catch (NoAlertPresentException | ElementNotSelectableException e) {
        LOGGER.info(LEARNER_MARKER,"Failed to send text '{}' to prompt window (ignoreFailure: {},negated);

        return getFailedOutput();
    }
}
项目:bromium    文件:ClickClassByTextTest.java   
@Test
public void throwsExceptionIfNoElementsAreFound() {
    List<WebElement> webElements = new ArrayList<>();

    By elementsLocator = By.className(initialCollectorClass);
    WebDriver webDriver = mock(WebDriver.class);
    when(webDriver.findElements(elementsLocator)).thenReturn(webElements);

    ClickClassByText clickClassByText = new ClickClassByText(initialCollectorClass,mock(ReplayingState.class));
}

关于Selenium:遍历一组元素时如何避免StaleElementReferenceException?selenium遍历子元素的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于frameToBeAvailableAndSwitchToIt 之后的 Selenium StaleElementReferenceException、How to avoid “StaleElementReferenceException” in Selenium?、java+selenium报异常org.openqa.selenium.StaleElementReferenceException的解决方案、org.openqa.selenium.ElementNotSelectableException的实例源码的相关信息,请在本站寻找。

本文标签: