使用硒等待进度条

时间:2020-03-21 05:19:08

标签: java selenium xpath

我正在尝试使用Selenium等待进度条出现和消失,这表明搜索结果已经开始并且已经完成。

没有进度条时,文档看起来像这样:

<html lang="en-US">
    <body class="appian-body">
        <a id="skip-to-content"></a>
        <div id="aDiv"></div>
        <div id="anotherOne"></div>
        <div id="OneMore"></div>
        ...
    </body>
</html>

搜索通话开始时,看起来像这样:

<html lang="en-US">
    <body class="appian-body">
        <a id="skip-to-content"></a>
        <div id="aDiv"></div>
        <div id="anotherOne"></div>
        <div id="OneMore"></div>
        ...
        <div id="appian-working-indicator-hidden" style="display: none;"></div>
    </body>
</html>

请注意<div id="appian-working-indicator-hidden" style="display: none;"></div>已经出现,这也是进度条出现的时候。当然,搜索完成后它就会消失,然后我们回到原始文档。

以下是我为等待该元素而做的一些尝试:

尝试1

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[4]")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("/html/body/div[4]")));

结果visibilityOfElementLocated上的超时异常(即从不可见)。

尝试2

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("/html/body/div[4]")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("/html/body/div[4]")));

结果:执行完全通过presenceOfElementLocatedinvisibilityOfElementLocated进行,而无需等待。

那么,还可以做些什么来确保此元素出现和消失?

更新

我创建了这些递归方法:

public void waitForProgressBarToStart() {
    List<WebElement> progressBarList = driver.findElements(By.xpath("//div[@id='appian-working-indicator-hidden']"));
    if(progressBarList.size() == 0) {
        waitForProgressBarToStart();
    } else {
        //for timestamping when the element is found
        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();
        System.out.println(String.format("%s: Progress Bar started", dateFormat.format(date)));
    }
}
public void waitForProgressBarToFinish() {
    List<WebElement> progressBarList = driver.findElements(By.xpath("//div[@id='appian-working-indicator-hidden']"));
    if(progressBarList.size() > 0) {
        waitForProgressBarToFinish();
    } else {
        //for timestamping when the element is gone
        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();
        System.out.println(String.format("%s: Progress Bar done", dateFormat.format(date)));
    }
}
public void waitForResults(){
    waitForProgressBarToStart();
    waitForProgressBarToFinish();
}

在方法中使用了时间戳记后,我可以看到waitForProgressBarToFinish方法比实际进度条花费10-13秒的时间。 waitForProgressBarToStart似乎在正确的时间找到了元素。

waitForProgressBarToFinish为什么需要更长的时间以及如何解决?

4 个答案:

答案 0 :(得分:1)

由于您知道要专门查找ID值为<div>的{​​{1}}元素,因此应使用更具体的xpath查询来查找它。我希望您的“尝试2”执行立即通过,因为WebDriver位于页面的第四个appian-working-indicator-hidden上,而这可能不是您要查找的<div>

您可以查询具有特定ID值using the contains() xpath functiondiv#appian-working-indicator-hidden

您可能会重写“尝试2”,使其看起来像这样:

<div>

答案 1 :(得分:1)

您可以获取该Web元素的列表,当该元素在页面上可见时,列表的大小将为1,而当该元素不可见时,列表的大小将为0。因此,您可以检查检查它是否可见的元素。

我正在为您的元素使用相对xpath而不是您正在使用的绝对xpath,因为绝对xpath非常易变,并且html结构中的任何细微更改都可能对脚本产生影响。

您的代码应类似于:

List<WebElement> progressBarList = driver.findElements(By.xpath("//div[@id='appian-working-indicator-hidden']"));
if(progressBarList.size()>0){
    System.out.println("Element is present");
}
else{
    System.out.println("Element is not present");
}

答案 2 :(得分:1)

为此,我使用纯 JS 以便我可以逃避 Selenium 中的内置等待。当涉及到 Selenium 时,否定查找一直是一个大问题

Supplier<Boolean> isLoadingCheck = () -> (Boolean) js.executeScript(
    "return (document.getElementById('nprogress') != null || document.getElementsByClassName('spinner').length > 0)"
);

答案 3 :(得分:0)

你使用的逻辑很好。为了防止时间溢出,您可以覆盖第二个方法调用的隐式等待时间,并将其重置为 finally 块中的原始值。 我认为当它在停止时隐式搜索进度条时,时间会流逝。