提问者:小点点

WebDriver等待'。直到(期望条件。elementToBeClickable'仅在我将Thread.睡眠(500)添加到代码时有效?


>

  • 我试图点击一个按钮,这是可见的页面上使用web驱动程序等待,但web驱动程序只能点击按钮,一旦我添加一个线程.睡眠到代码。

    在执行代码之前,我还检查了按钮以查看它是否可见(True),然后返回=true

    //按钮可见性检查:

    List<WebElement> signOutList = driver.findElements(.xpath(".//*[starts-with(@id,'fulfillment-time-type-section-')]/div[2]//button"));
    Assert.assertTrue(signOutList.size() > 0);
    

    //下面的代码没有点击按钮

    By timeDropdownButton = By.xpath(".//*[starts-with(@id,'fulfillment-time-type-section-')]/div[2]//button");
    WebElement myDynamicElement = (new WebDriverWait(driver, 10))
                  .until(ExpectedConditions.elementToBeClickable(timeDropdownButton));
    myDynamicElement.click();
    

    //下面的代码是否点击按钮:

    Thread.sleep(500);
    By timeDropdownButton = By.xpath(".//*[starts-with(@id,'fulfillment-time-type-section-')]/div[2]//button");
    WebElement myDynamicElement = (new WebDriverWait(driver, 10))
                  .until(ExpectedConditions.elementToBeClickable(timeDropdownButton));
    myDynamicElement.click();
    


    请注意,我还尝试使用JS代码和WebDriver操作等单击按钮

    我不知道为什么“等待点击”只在我与“线程.睡眠”结合时有效?

    我想点击的按钮


  • 共3个答案

    匿名用户

    一般来说,您希望尽可能避免在测试中使用Thread.睡眠。仅仅几个测试可能看起来不那么重要,但它们的使用中固有的很多问题。首先,如果您有一堆测试,测试套件的运行时间可能会变得难以管理。其次,它们有时是不够的。例如,对于一般的生产机器,等待500毫秒可能就足够了,但如果Web服务器负载较重或处于测试环境中,则可能需要750毫秒才能准备好。然后您将处理非确定性故障。最好使用像WebDriver等这样的结构,并给它们一个合理的(但过于慷慨的)最大值,这样你就不必等待超过必要的时间,但如果它失败了,这意味着测试环境有严重的问题。

    此外,必胜客网站在这里大量使用异步java脚本和浮动面板等。在使用Selenium时,所有这些都需要更加小心,因为元素需要在与它们交互之前准备好,但它们通常已经在DOM中。这意味着默认情况下,Selenium可能会在JavaScript完成之前快速找到它们,并且它们实际上并未处于准备使用状态。您将希望像您已经尝试过的那样使用期望条件。您遇到问题的按钮需要等待JavaScript完成,这是已经建议的,但它不需要在页面加载中,而是在单击按钮之前。在我的机器上工作的示例:

    @Test
    public void foo() {
        WebDriver driver = new FirefoxDriver();
        driver.manage()
              .window()
              .maximize();
        // Move through the page to the point you are interested in
        driver.get("https://www.pizzahut.co.uk/");
        waitForElement(driver, By.cssSelector(".hidden-xs [title='Pizza']")).click();
        waitForElement(driver, By.cssSelector("form[action='/menu/startyourorder']")).submit();
        WebElement postElement = waitForElement(driver, By.id("ajax-postcode-txt"));
        postElement.sendKeys("TS1 4AG" + Keys.ENTER);
        // Wait for the java script to finish executing
        waitForJavaScript(driver);
        // Finally you should be able to click on the link
        waitForElement(driver, By.partialLinkText("Start Your Order")).click();
        // continue on ... then quit the driver
        driver.quit();
    }
    
    private WebElement waitForElement(WebDriver driver, By locator) {
        return new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(locator));
    }
    
    private void waitForJavaScript(WebDriver driver) {
        new WebDriverWait(driver, 10).until(new Predicate<WebDriver>() {
                                                public boolean apply(WebDriver driver) {
                                                    return ((JavascriptExecutor) driver).executeScript("return document.readyState")
                                                                                        .equals("complete");
                                                }
                                            }
        );
    }
    

    在WebDriver等中,给定的int参数是它将继续尝试给定检查的秒数。如果它达到设置的数量(上面示例中的10秒),它将抛出TimeoutException

    匿名用户

    页面上可能仍在执行活动的Javascript。在第一瞬间,它可能会以期望条件无法分辨的方式修改它。当我遇到意外行为的问题时,我发现等待页面加载(包括javascript脚本)通常可以解决大部分问题。

    要等待页面加载,您可以调用您的一些Javascript来检查文档的readyState。尝试等待页面加载,然后等待元素可点击。

    快速搜索返回这个(代码取自此处):

    wait.until( new Predicate<WebDriver>() {
                public boolean apply(WebDriver driver) {
                    return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
                }
            }
        );
    

    匿名用户

    以下方法似乎工作正确:

    public void waitForPageLoad() {
        ExpectedCondition<Boolean> expectation = new
                ExpectedCondition<Boolean>() {
                    public Boolean apply(WebDriver driver) {
                        return ((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete");
                    }
                };
        try {
            Thread.sleep(1000);
            WebDriverWait wait = new WebDriverWait(driver, 30);
            wait.until(expectation);
        } catch (Throwable error) {
            Assert.fail("Timeout waiting for Page Load Request to complete.");
        }
    }