【问题标题】:Selenium : Element is found when using Thread.sleep(), but not Implicit/Explicit waitsSelenium:使用 Thread.sleep() 时找到元素,但没有隐式/显式等待
【发布时间】:2021-12-03 16:40:47
【问题描述】:

我了解了使用隐式/显式等待的好处,并决定在我的代码中放弃 Thread.sleep()。然而,结果却适得其反。使用 Thread.sleep(),我实际上可以定位元素,而隐式/显式等待会导致同一元素出现 ElementClickInterceptedException: element click intercepted: [duplicate] 错误。

我试图模拟点击的元素是位于对话框中的“我同意”按钮。以下是我尝试单击的按钮的 DOM。

下面是模拟点击的代码。

使用隐式等待

driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();

结果: ElementClickInterceptedException:元素点击被拦截:[重复]错误

使用显式等待

WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement I_Agree; 
I_Agree = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[1]/div/div/div[4]/a")));
I_Agree.click();

结果: ElementClickInterceptedException:元素点击被拦截:[重复]错误

使用 Thread.sleep()

Thread.sleep(20000);
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();

结果:找到元素,可以执行点击。

希望对我可能犯的任何错误提出建议。

【问题讨论】:

    标签: java selenium-webdriver


    【解决方案1】:

    implicitlyWait 等待元素存在。 所以在

    的情况下
    driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
    

    Selenium 将在目标元素出现后立即尝试单击该元素。
    在许多情况下,该元素仍然无法点击,因此使用 implicitlyWait 可能经常会导致异常。
    使用ExpectedConditions.visibilityOfElementLocated 会更好地工作,但仍然有几种情况不起作用。
    在某些情况下,目标元素可能不在可见屏幕之外。在这种情况下,您必须滚动到目标元素才能将其带入可见屏幕,然后正确单击它。
    在页面渲染期间的其他一些情况下,Selenium 将指示元素为可见和可点击,而实际上一些其他元素可能与目标元素重叠,因此点击它会导致错误的元素接受点击。但是,如果您再等待一段时间,页面渲染过程将完成,现在您可以正确单击目标元素。
    这似乎是你的情况。
    在大多数情况下,重叠元素将是某种微调器元素。
    如果是这样,您应该添加ExpectedConditions.invisibilityOfElementLocated 条件以等待微调器/其他重叠元素消失。
    为了给出更准确的答案,我们需要查看您正在处理的特定站点以及您正在执行的实际测试流程。
    您可以查看更多关于 ElementClickInterceptedException here、here、here 以及更多资源的信息。
    UPD
    从你的 cmets 我看你并没有真正理解。隐式和显式等待都在池化 DOM 以查找匹配传递条件的元素。在这两种情况下,当满足条件时,Selenium 将立即停止等待和轮询,它会返回一个元素(或在某些情况下为布尔值 true)并继续执行下一个命令。
    隐式等待是等待元素存在。因此,在许多情况下,元素本身仍未最终呈现,并且可能仍然不可点击或可见,但它已经存在,所以在您的情况下

    driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a"))
    

    可能会返回尚未准备好被点击的元素。
    这就是为什么首选使用像ExpectedConditions.visibilityOfElementLocated 这样的显式等待的原因,因为在这种情况下,Selenium 将等待轮询 DOM,直到找到所需的元素 可见,这是元素的更成熟的状态在页面上,此时可以正常点击。
    但是,有时它可能是该元素上的一些微调器等。这是一些外部问题。因此,在这种情况下,我们需要添加 ExpectedConditions.invisibilityOfElementLocated 以等待该微调器消失。
    在更多情况下,显式等待不足以应用于元素本身。有时您必须将所需的元素滚动到视图中,有时您甚至需要使用 JavaScript click 等。

    【讨论】:

    • 感谢您的解释。它开始变得有意义。根据您对特定站点的要求,我将在此处附上视频youtube.com/watch?v=FjId9-2IFTU,因为需要一个帐户才能登录并导航到所述站点。
    • 顺便说一句,既然我“手动”通过使用 Thread.sleep() 给予更多等待来真正确保渲染完成,为什么不能隐式/显式这样做呢?我已将隐式/显式计时器设置为比 Thread.sleep() 更长的时间段,但它不断向我返回 ElementClickInterceptedException 错误。提前感谢您的澄清。
    • 请看我更新的答案
    • 从视频中看不太清楚我们在这里谈论的元素出现在哪里。
    猜你喜欢
    • 2012-12-08
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多