WebDriverWait 用法代码
WebDriverWait(
driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
参数解析:
WebDriverWait(WebDriver driver, long timeOutInSeconds)
Java 版本常用的有两个参数,参数解析:
WebDriverWait 通常与 until 和 util_not 结合使用,Java 与 Python 用法相同。
expected_conditions 是 Selenium 的一个模块,其中包含一系列可用于判断的条件。可以用来判断页面的元素是否可见,是否可点击等操作。
需要先导入这个模块,导入代码如下:
from selenium.webdriver.support import expected_conditions
import org.openqa.selenium.support.ui.ExpectedConditions;
1.判断元素是否被加到了 DOM 树里,并不代表该元素一定可见,用法如下:
WebDriverWait().until(
expected_conditions.presence_of_element_located(locator))
new WebDriverWait( )\
.until(ExpectedConditions.presenceOfElementLocated(locator));
2.visibility_of_element_located(locator) 方法,用来判断某个元素是否可见(可见代表元素非隐藏,并且元素的宽和高都不等于 0,用法如下:
WebDriverWait().until(
expected_conditions.visibility_of_element_located(locator))
new WebDriverWait( ).until(
ExpectedConditions.visibilityOfElementLocated(locator));
3.element_to_be_clickable(locator) 方法,判断某元素是否可见并能点击,用法如下:
WebDriverWait().until(
expected_conditions.element_to_be_clickable((By.ID, "kw")))
new WebDriverWait( ).until(
ExpectedConditions.elementToBeClickable(locator));
使用“雪球”应用,打开雪球 APP,点击页面上的搜索输入框输入“alibaba”,然后在搜索联想出来的列表里面点击“阿里巴巴”,选择股票分类,获取股票类型为“09988”的股票价格,最后验证价格大于 170,核心代码如下:
...
def test_wait(self):
# 点击搜索输入框
self.driver.find_element_by_id(
"com.xueqiu.android:id/tv_search").click()
# 输入 “alibaba”
self.driver.find_element_by_id(
"com.xueqiu.android:id/search_input_text"
).send_keys("alibaba")
# 点击“阿里巴巴”
self.driver.find_element_by_xpath("//*[@text='阿里巴巴']").click()
# 点击“股票”
self.driver.find_element_by_xpath(
"//*[contains(@resource-id,'title_container')]//*[@text='股票']"
).click()
# 获取股票价格
locator = (MobileBy.XPATH,
"//*[@text='09988']/../../..\
//*[@resource-id='com.xueqiu.android:id/current_price'")
ele = WebDriverWait(self.driver,10)\
.until(expected_conditions.element_to_be_clickable(locator))
print(ele.text)
current_price = float(ele.text)
expect_price = 170
# 判断价格大于 expect_price
assert current_price > expect_price
...
...
private final By locator = By.xpath("//*[@text='09988']/../../..\
//*[@resource-id='com.xueqiu.android:id/current_price'");
@Test
public void waitTest(){
// 点击搜索输入框
driver.findElementById("com.xueqiu.android:id/tv_search").click();
// 输入 “alibaba”
driver.findElementById("com.xueqiu.android:id/\
search_input_text").sendKeys("alibaba");
// 点击“阿里巴巴”
driver.findElementByXPath("//*[@text='阿里巴巴']").click();
// 点击“股票”
driver.findElementByXPath("//*[contains(@resource-id,\
'title_container')]//*[@text='股票']").click();
// 获取股票价格
WebDriverWait wait=new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(locator));
String locatorText = driver.findElement(locator).getText();
System.out.println(locatorText);
float currentPrice = Float.parseFloat(locatorText);
float expectPrice = 170;
//判断价格大于 expect_price
assertThat(currentPrice, greaterThan(expectPrice));
}
...
这条测试用例仅仅使用隐式等待是解决不了问题的,因为【当前价格】这个元素一直在,而实际需要等待的是这个元素是否处于可点击的状态。
上面的代码通过判断元素是否可点击的方法来判断元素是否处于可点击状态,中间添加了 10 秒的等待时间,在 10 秒之内每隔 0.5 秒查找一次元素,如果找到了这个元素,就继续向下执行,如果没找到就抛出 TimeoutException 异常信息。显式等待可以在某个元素上灵活的添加等待时长,尤其是文件上传,或者资源文件下载的场景中,可以添加显式等待,提高脚本的稳定性。
一般来说,在项目中会使用隐式等待与显式等待结合的方式,定义完 driver 之后立即设置一个隐式等待,在测试过程中需要判断某个元素属性的时候,再加上显式等待。