【问题标题】:check if a button is available? if not wait 5 seconds and check again?检查按钮是否可用?如果不等待 5 秒再检查一次?
【发布时间】:2019-08-08 17:20:52
【问题描述】:

基本上,我正在尝试查看当前是否可以单击按钮。如果没有,我想再试一次。所以我需要某种 goto 函数来返回我的代码的前一行。虽然我怀疑我写得非常糟糕,而且它本来可以做得更容易。

try {
    driver.findElement(By.xpath("//button[@id='btn_ok']")).click();
}catch (Exception e) {
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}   

对于上下文,这里是有问题的按钮罪魁祸首。

<button type="submit" value="ok" name="s1" id="btn_ok" class="green">

【问题讨论】:

  • disabled 属性怎么样?检查this!它可能会给你一个提示!
  • 呃,谢谢 M.K.但是该按钮在一天中的不同时间不可用。该网站每隔几分钟就会添加和删除它。
  • 嗨@sergiy,尝试使用 FluentWait(),每 5 秒忽略一次 NoSuchElementException 来检查按钮是否可用?
  • @sergiy 为什么要每隔 5 秒(这么长)检查按钮的可用性?您总共要检查多少次或多长时间?

标签: java selenium selenium-webdriver wait goto


【解决方案1】:

快速解答

请查看下面的代码,如果它解决了您的问题,请告知。

    public synchronized boolean clickOnButtonWhenItBecomesClickable() {
        boolean buttonClicked=false;
        try {
            List<WebElement> element = driver.findElements(By.xpath("//button[@id='btn_ok']"));

            while(element.size()!=0) {
                // if any action needed to perform to display button, please do it.
                element = driver.findElements(By.xpath("//button[@id='btn_ok']"));
                if(element.size()!=0) {
                    wait = new FluentWait<WebDriver>((WebDriver) driver).withTimeout(30, TimeUnit.SECONDS).pollingEvery(5,
                            TimeUnit.SECONDS);
                    wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.xpath("//button[@id='btn_ok']"))));
                    buttonClicked=true;
                    break;  
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return buttonClicked;
    }

【讨论】:

  • 谢谢,但它说 withTimeout 已被弃用,pollingEvery 也是如此
【解决方案2】:

我更喜欢这个,因为它可以接受任何布尔条件来“等到”。

    public static void WaitUntil(this IWebDriver driver, Func<bool> Condition, float timeout = 10f)
    {

        float timer = timeout;
        while (!Condition.Invoke() && timer > 0f) {

            System.Threading.Thread.Sleep(500);
            timer -= 0.5f;

        }
        System.Threading.Thread.Sleep(500);

    }

    driver.WaitUntil(() => driver.FindElements(By.XPath("some xpath...").Length == 0);

    //Here is the particular benefit over normal Selenium waits. Being able to wait for things that have utterly nothing to do with Selenium, but are still sometimes valid things to wait for.
    driver.WaitUntil(() => "Something exists in the database");

我发现隐含的等待给我带来的麻烦多于它的价值。而且我发现显式硒等待可能会有点冗长,并且它并没有涵盖我在我的框架中需要的所有内容,所以我做了很多扩展。这是其中之一。请注意,我在上面的示例中使用 FindElements,因为我不希望在找不到任何内容时引发异常。这应该适合你。

注意:这是 C#,但对任何语言(尤其是 Java)进行修改都不难。如果您的语言不允许这样的扩展,只需直接在类中调用该方法即可。您需要将其放在静态类中才能正常工作。在逻辑上扩展这样的现有类时要小心,因为当其他人试图确定方法的定义位置时,这可能会使他们感到困惑。

【讨论】:

    【解决方案3】:

    您可以使用显式等待来等待按钮可点击。它将每 500 毫秒测试一次按钮,最长指定时间,直到它可以点击

    WebDriverWait wait = new WebDriverWait(driver, 5); // maximum wait time is 5 here, can be set to longer time
    WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.id("btn_ok")));
    button.click();
    

    附带说明,implicitlyWait 设置驱动程序搜索元素的最长时间,它不会延迟脚本。

    【讨论】:

      【解决方案4】:

      您可以使用流利的等待。这将每隔 5 秒检查一次按钮是否可点击,持续 30 秒。您可以根据需要调整时间。试试这个代码并给出反馈是否有效。

       Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)                           
                      .withTimeout(30, TimeUnit.SECONDS)          
                      .pollingEvery(5, TimeUnit.SECONDS)          
                      .ignoring(NoSuchElementException.class);
              WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>(){
      
                  public WebElement apply(WebDriver driver ) {
                      return driver.findElement(By.xpath("//button[@id='btn_ok']"));
                  }
              });
              clickseleniumlink.click();
      

      【讨论】:

      • 为什么要避免使用量身定制且久经考验的 WebDriverWait
      【解决方案5】:

      试试这个方法。看看是否有帮助。

      int size=driver.findElements(By.xpath("//button[@id='btn_ok']")).size();
      if (size>0)
        {
          driver.findElement(By.xpath("//button[@id='btn_ok']")).click();
        }
        else
        {
          driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
          int size1=driver.findElements(By.xpath("//button[@id='btn_ok']")).size();
          if (size1>0)
        {
          driver.findElement(By.xpath("//button[@id='btn_ok']")).click();
        }
      
      
      
      }   
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-16
        • 1970-01-01
        • 2022-11-25
        • 1970-01-01
        • 2012-11-09
        • 1970-01-01
        相关资源
        最近更新 更多