自动化测试中,等待时间的运用占据了举足轻重的地位,平常我们需要处理很多和时间息息相关的场景,例如:
- 打开新页面,只要特定元素出现而不用等待页面全部加载完成就对其进行操作
- 设置等待某元素出现的时间,超时则抛出异常
- 设置页面加载的时间
- .....
webdriver类中有三个和时间相关的方法:
1.pageLoadTimeout 2.setScriptTimeout
3.implicitlyWait
我们就从这里开始,慢慢揭开他神秘的面纱。
pageLoadTimeout
pageLoadTimeout方法用来设置页面完全加载的超时时间,完全加载即页面全部渲染,异步同步脚本都执行完成。前面的文章都是使用get方法登录安居客网站,大家应该能感觉到每次打开网页后要等很长一段时间才会进行下一步的操作,那是因为没有设置超时时间而get方法默认是等待页面全部加载完成才会进入下一步骤,加入将超时时间设置为3S就会中断操作抛出异常
1 import java.util.concurrent.TimeUnit; 2 import org.openqa.selenium.By; 3 import org.openqa.selenium.WebDriver; 4 import org.openqa.selenium.chrome.ChromeDriver; 5 import org.openqa.selenium.WebElement; 6 7 public class NewTest{ 8 public static void main(String[] args) throws InterruptedException { 9 System.setProperty ( "webdriver.chrome.driver" , 10 "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe" ); 11 WebDriver driver = new ChromeDriver(); 12 try{ 13 //设置超时时间为3S 14 driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); 15 driver.get("http://shanghai.anjuke.com"); 16 17 WebElement input=driver.findElement(By.xpath("//input[@id='glb_search0']")); 18 input.sendKeys("selenium"); 19 20 }catch(Exception e){ 21 e.printStackTrace(); 22 }finally{ 23 Thread.sleep(3000); 24 driver.quit(); 25 } 26 }
ps:如果时间参数为负数,效果没有使用这个方法是一样的,接口注释中有相关说明:"If the timeout is negative, page loads can be indefinite".
如果想在抛出异常后并不中断而是继续执行下面的操作那该怎么办呢?可以使用try,catch的组合来实现这个功能
1 import java.util.concurrent.TimeUnit; 2 import org.openqa.selenium.By; 3 import org.openqa.selenium.WebDriver; 4 import org.openqa.selenium.chrome.ChromeDriver; 5 import org.openqa.selenium.WebElement; 6 7 public class NewTest{ 8 public static void main(String[] args) throws InterruptedException { 9 System.setProperty ( "webdriver.chrome.driver" , 10 "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe" ); 11 WebDriver driver = new ChromeDriver(); 12 try{ 13 //设置超时时间为3S 14 driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); 15 driver.get("http://shanghai.anjuke.com"); 16 }catch(Exception e){ 17 18 }finally{ 19 WebElement input=driver.findElement(By.xpath("//input[@id='glb_search0']")); 20 if(input.isDisplayed()) 21 input.sendKeys("selenium"); 22 } 23 }
这样,当页面加载3S后就会执行下面的操作了。
setScriptTimeout
设置异步脚本的超时时间,用法同pageLoadTimeout一样就不再写了,异步脚本也就是有async属性的JS脚本,可以在页面解析的同时执行。
implicitlyWait
识别对象的超时时间,如果在设置的时间类没有找到就抛出一个NoSuchElement异常,用法参数也是和pageLoadTimeout一样,大家可以自己试验试验。
上文中介绍了如何才能在使用pageLoadTimeout抛出异常的同时继续执行,但是现有的方法还是不完美,如果输入框在3S后没有出现还是会报错,怎么办呢?机智的同学可以想到用sleep方法来实现,为了方便演示换个更明显的需求来说明。安居客的首页上有个切换城市的链接,当点击城市的时候就会显示全部的城市以供选择这时display属性就会变化
1 import java.util.concurrent.TimeUnit; 2 import org.openqa.selenium.By; 3 import org.openqa.selenium.WebDriver; 4 import org.openqa.selenium.chrome.ChromeDriver; 5 import org.openqa.selenium.WebElement; 6 import org.openqa.selenium.interactions.Actions; 7 8 public class NewTest{ 9 public static void main(String[] args) throws InterruptedException { 10 System.setProperty ( "webdriver.chrome.driver" , 11 "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe" ); 12 WebDriver driver = new ChromeDriver(); 13 try{ 14 //设置超时时间为3S 15 driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); 16 driver.get("http://shanghai.anjuke.com"); 17 }catch(Exception e){ 18 19 }finally{ 20 WebElement city=driver.findElement(By.xpath("//a[@id='switch_apf_id_8']")); 21 WebElement citys=driver.findElement(By.xpath("//div[@id='city-panel']")); 22 Actions actions=new Actions(driver); 23 actions.clickAndHold(city).perform(); 24 while(citys.isDisplayed()){ 25 System.out.println("sleep"); 26 Thread.sleep(3000); 27 } 28 Thread.sleep(3000); 29 driver.quit(); 30 } 31 32 }
执行后会每过3S就会输出一次sleep,但是这样的代码显然不够高大上,而且没有限制会一直无限的等待下去,下面介绍一种高大上的方法,就是until,先看代码
1 import org.openqa.selenium.By; 2 import org.openqa.selenium.WebDriver; 3 import org.openqa.selenium.chrome.ChromeDriver; 4 import org.openqa.selenium.WebElement; 5 import org.openqa.selenium.interactions.Actions; 6 import org.openqa.selenium.support.ui.WebDriverWait; 7 import org.openqa.selenium.support.ui.ExpectedCondition; 8 9 public class NewTest{ 10 public static void main(String[] args) throws InterruptedException { 11 System.setProperty ( "webdriver.chrome.driver" , 12 "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe" ); 13 WebDriver driver = new ChromeDriver(); 14 try{ 15 //设置超时时间为3S 16 driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); 17 driver.get("http://shanghai.anjuke.com"); 18 }catch(Exception e){ 19 20 }finally{ 21 WebElement city=driver.findElement(By.xpath("//a[@id='switch_apf_id_8']")); 22 Actions actions=new Actions(driver); 23 actions.clickAndHold(city).perform(); 24 25 //最多等待10S,每2S检查一次 26 WebDriverWait wait=new WebDriverWait(driver,10,2000); 27 28 wait.until(new ExpectedCondition<Boolean>() { 29 public Boolean apply(WebDriver driver) { 30 System.out.println("sleep"); 31 return !driver.findElement(By.xpath("//div[@id='city-panel']")).isDisplayed(); 32 } 33 }); 34 35 Thread.sleep(3000); 36 driver.quit(); 37 } 38 39 }
效果是每隔2S输出一个sleep,输出5次后抛出超时异常,简单明了,高大上。