Selenium網站自動化測試:如何讓程式等待某個網頁元件?
這篇文章主要要解決自動化測試常見的失敗:網頁元件找不到。由於Selenium是實際用瀏覽器載入網頁,
因此網頁上的相關網頁元件的出現的時間點常會取決於系統環境的影響。
例如:網路的因素或是瀏覽器載入的時間等。或是,該網頁元件是動態的元件,要觸發某個事件之後,該網頁元件才會出現。
不管是因為系統環境造成或是觸發事件造成,Selenium要怎樣解決這些問題呢?
測試情境
我們將用 Google為例子,進行這樣的測試
1. 啟動Chorme 瀏覽器
2.瀏覽 WWW.Google.com
3. 出現 Search box 的時候輸入 “Selenium”
問題來了,Selenium怎麼知道什麼時候 Google Search Box 會出現呢?
是瀏覽器開啟 google網站後 1 秒鐘? 還是 10秒鐘?
如果Selenium程式在 SearchBox還沒有出現的時候就輸入,那麼就會發生非預期的錯誤。
因此,我們要適當的導引 Selenium需要 “等待”
如何等待網頁元件
Selenium提供兩種方式可以做網頁元件等待的處理。
- implicitly Wait: 這種等待通常適用在整個程式的預設等待。因此這樣的等待方式也是最常用的。當網頁元件暫時找不到時,程式會進行等待,等到所指定的timeout為止。
- Explicit Wait: 這種等待通常是針對特別指定的網頁元件。通常我們不會每一個網頁元件都做這樣的等待。只要針對”特別”的網頁元件。
- Thread.sleep(1000): 等待 1秒。這是最簡單也是最直接的方式。無論如何,執行道這行程式就會進入等待 10 sec,讓網頁有些時間可以完成下載與顯示的動作。
程式說明
implicitly Wait
通常程式一開始會定義implicitly wait,也就是告訴 Selenium 程式預設等待 10秒。
如果有任何網頁元件找不到,等10秒。10秒內如果該網頁元件出現,那麼程式就會繼續執行。
筆者建議任何 Selenium的程式一開頭都要加入這樣的等待定義。
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); |
Explicit Wait
其中 Explicit Wait讀者會好奇問,什麼是”特別”的網頁元件?什麼情況需要特別使用 Explicit Wait呢?
就是當使用implicitly Wait之後,自動化測試執行時,對於一些網頁元件經常Element not found的錯誤。
但是檢查該網頁確實又存在該網頁元件。像這樣的情況,我們就會特別使用 Explicit Wait
Explicit Wait 的寫法有很多,筆者覺得比較簡潔的方式如下:
WebDriverWait wait = new WebDriverWait(driver, 10); WebElement SearchText = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(“//input[@name=’q’]”))); |
Explicit Wait 可以定義等待的條件,ExpectedConditions
例如這個例,”presenceOfElementLocated” 元件是否存在。當然還有許多各種的條件可以定義,例如是否可以點選、是否可以看見等。
presenceOfElementLocated 與visibilityOfElementLocated是兩個比較通用的,可以用來等待到該原件存在或是出現為止。
Thread.sleep(1000)
什麼情況下用這種刻意等待時間? 當上面兩種情況下的等待使用之後,
自動化程式執行時,還是會經常遇到 Element not found 的錯誤時候,
首先可以嘗試將上面 implicit wait & explicit wait 的時間拉長,
還是會發生網頁元件找不到的錯誤時,就可以考慮使用等待特定時間 Thread.sleep
有些狀況,用這樣的等待,確實就可以讓自動化測試程式的失敗率大幅降低。
缺點是,到底要等 1 sec or 5 sec or 1sec ?
如果整個程式到處都是 sleep 除了程式會越跑越慢,也會越來越難維護。
程式範例
[pastacode lang=”java” message=”Selenium Wait” highlight=”” provider=”manual”]
package mySelenium;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class testChrome {
public static void main(String[] args) {
// Download the Chrome WebDriver here
// http://chromedriver.storage.googleapis.com/index.html?path=2.15/
System.setProperty("webdriver.chrome.driver", "c:\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://www.google.com");
// This is to tell Selenium wait for the search button
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement SearchText = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@name='q']")));
SearchText.sendKeys("Selenium");
//driver.findElement(By.xpath("//input[@name='q']")).sendKeys("Selenium");
}
}
[/pastacode]