这里是udemy course(来自“ Lets Kode It”),用于开发使用硒和Java的Web自动化框架。 但是,这不是Java问题。您只需要了解以下任何一种语言中的硒-javascript,python,ruby,c#和java。
讲师开发了一个CustomDriver类,该类具有以下给出的方法/功能。该方法等待元素可单击,而不必在我们的代码中到处编写WebDriverWait
语句。它首先将隐式等待设置为零,然后进行显式等待,然后将隐式等待设置为框架中使用的原始值。
这种方法对我来说似乎还可以,但我不确定。这样混合隐式等待和显式等待会导致任何问题吗?
/*
Click element when element is clickable
@param locator - locator strategy, id=>example, name=>example, css=>#example,
tag=>example, xpath=>//example, link=>example
@param timeout - Duration to try before timeout
*/
public void clickWhenReady(By locator, int timeout) {
try {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
WebElement element = null;
System.out.println("Waiting for max:: " + timeout + " seconds for element to be clickable");
WebDriverWait wait = new WebDriverWait(driver, 15);
element = wait.until(
ExpectedConditions.elementToBeClickable(locator));
element.click();
System.out.println("Element clicked on the web page");
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
} catch (Exception e) {
System.out.println("Element not appeared on the web page");
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
}
}
我不建议混合使用。由于Implicit wait
通常是在WebDriver系统的remote
端实现的,这意味着它们是在基于浏览器的驱动程序(例如chromedriver.exe,IEDriverServer.exe)中处理的,而Explicit Wait
是在本地语言绑定,例如Java,ruby,python等。
下面是典型示例,用remote server
运行脚本时会发生什么。
本地代码->远程服务器->远程服务器上的本地语言绑定->远程组件,例如chromedriver.exe或IEDriverServer.exe。如果涉及到网格,事情就会变得更加复杂,因为它可能是链之间的另一层。
因此,当您同时使用隐式等待和显式等待时,可能会出现不确定的行为。而且,由于隐式等待是在驱动程序级别实现的,因此它们随时可能更改,并且会对脚本产生影响。因此,最好始终坚持明确等待并完全控制。
使用当前技术,元素可能会在元素出现后立即渲染。因此,仅使用implicit wait
是不够的,因此强烈希望使用explicit wait
。在某些情况下,我们可能必须使用implicit wait
,但如果您打算将来扩展脚本以在网格上/使用远程服务器运行,则切勿将两者混用。
您实际上并没有同时混合两种不同的等待类型。但是是的,您的代码不是很好。请看下面我长期以来一直在使用的代码(我给您的想法),并成功地对正/负方案执行测试。您可以使用“ finally”来确保隐式返回到分配的等待时间。
public static void waitForElementToBeClickableByLocator(WebDriver driver, By locator) {
try {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
wait = new WebDriverWait(driver, 30)
.ignoring(NoSuchElementException.class, StaleElementReferenceException.class)
.pollingEvery((Duration.ofSeconds(SECONDS));
wait.until(ExpectedConditions.elementToBeClickable(locator));
Log.info("Element is clickable");
}
catch (Exception e) {
Log.error(e.getMessage());
Assert.fail("Element is not clickable by locator: " + locator);
}
finally {
driver.manage().timeouts().implicitlyWait(Constants.implicitWaitTime, TimeUnit.SECONDS);
}
}
使用隐式等待和显式等待的问题归结为Selenium源代码中如何实现ExpectedConditions
的缺陷。
让我通过分析以下代码来解释问题:
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebElement element = new WebDriverWait(driver, 5, 1000).until(ExpectedConditions.elementToBeClickable(By.id("some_id")));
driver.findElement()
将等待10秒,直到找到元素为止,然后才抛出NoSuchElementException
。 这是要注意的非常重要的一点。WebDriverWait
将每1秒至5秒轮询一次ExpectedConditions
为真。如果ExpectedConditions
返回true,则轮询将停止,并返回ExpectedConditions
中指定的对象。在上面的示例代码中,返回的对象为WebElement
。如果5秒钟后ExpectedConditions
为假,则抛出TimeoutException
(或我们期望)。现在该看看ExpectedConditions
中发生了什么。ExpectedConditions.elementToBeClickable()
代码具有以下语法。
public static ExpectedCondition<WebElement> elementToBeClickable(final By locator) {
return new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
WebElement element = visibilityOfElementLocated(locator).apply(driver);
try {
if (element != null && element.isEnabled()) {
return element;
}
return null;
} catch (StaleElementReferenceException e) {
return null;
}
}
};
}
上面的elementToBeClickable
依次调用visibilityOfElementLocated()
方法以确认元素是否可见。
public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) {
return new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
try {
return elementIfVisible(driver.findElement(locator));
} catch (StaleElementReferenceException e) {
return null;
}
}
};
}
5。注意上面在driver.findElement(locator)
方法中如何调用visibilityOfElementLocated()
。如果找不到该元素,则将隐式等待10秒。因此,驱动程序将等待10秒钟,直到它抛出NoSuchElementException
。
但请等待(双关语不是故意的!在elementToBeClickable()
条件下,我们的显式等待是否设置为在5秒后超时?是的,但是隐式等待将首先应用。 WebDriverWait将捕获NoSuchElementException
并在10秒后抛出TimeoutException
,而不是设置的显式等待5秒。这就是问题中的解决方案试图解决的问题。解决方案尝试将隐式等待设置为0秒,以便正确执行显式等待条件,然后重置隐式等待。
课题中提供的实施确实完成了工作,没有一个细节。隐式等待被硬编码为3秒,这是不理想的。您如何将隐式等待作为全局通用常量来提供是特定于案例的。我们正在对驱动程序设置隐式等待,我们可以期望像“ driver” driver.manage().timeouts().getImplicitWait()
这样的隐式等待。虽然很理想,但是不幸的是这不可能直接实现。有解决方法,@ forresthopkinsa在创建用于获取隐式等待的扩展驱动程序方面有一个不错的interesting solution