自動化測試中,等待時間的運用占據了舉足輕重的地位,平常我們需要處理很多和時間息息相關的場景,例如:
- 打開新頁面,只要特定元素出現而不用等待頁面全部加載完成就對其進行操作
- 設置等待某元素出現的時間,超時則拋出異常
- 設置頁面加載的時間
- .....
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次后拋出超時異常,簡單明了,高大上。