2017-08-02 241 views
2

看來,Selenium的SafariDriver不會等待網頁加載。我的測試如下:Selenium SafariDriver不會等待頁面加載?

import org.junit.After; 
import org.junit.Before; 
import org.junit.Test; 
import org.openqa.selenium.By; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.chrome.ChromeDriver; 
import org.openqa.selenium.safari.SafariDriver; 

public class SafariTest { 

    private WebDriver driver; 

    @Before 
    public void setUp() throws Exception { 
     driver = new SafariDriver(); 
    } 

    @After 
    public void tearDown() throws Exception { 
     driver.close(); 
    } 

    @Test 
    public void testGoogleSearch() { 
     driver.get("http://duckduckgo.com"); 
     driver.findElement(By.id("search_form_input_homepage")).sendKeys("Hello World"); 
     driver.findElement(By.id("search_button_homepage")).click(); 
     driver.findElement(By.linkText("Images")).click(); 
    } 
} 

如果你運行這個與ChromeDriver,或FirefoxDriver,它的功能,因爲它應該,即它搜索的「Hello World」,然後在結果頁面上,這是不言而喻的圖像效果。

隨着SafariDriver,它失敗:

org.openqa.selenium.NoSuchElementException: An element could not be located on the page using the given search parameters. (WARNING: The server did not provide any stacktrace information) 

不能被發現是「圖像」,因爲之前跑了聲明的頁面沒有加載的元素。

這是預期的行爲?我應該爲Safari特例嗎?

+0

這可能是Safari瀏覽器在某些方面只是比較慢,導致此頁面出現問題。一般來說,你應該使用** [顯式等待](https://stackoverflow.com/questions/10404160/when-to-use-explicit-wait-vs-implicit-wait-in-selenium-webdriver)** 。或者我猜**如果你想鎖定自己沒有靈活性使用**顯式等待**,則隱式等待**,因爲硒文檔由於意外的等待時間而警告不要混合它們。 – mrfreester

+0

@mrfreester爲什麼應該顯式等待? – Roxy

+0

**如果使用隱式等待**,應該只在測試套件開始時設置一次。但是,通常人們會在測試套件中改變它們,這在將來的測試等待時間和難以追蹤的微小錯誤中導致不可預測性。 **隱式等待**也只等待元素爲__exist__,這並不總意味着元素已準備好與之交互。通過**顯式等待**,您可以清楚地表明您正在等待**可見**,**可點擊**或其他任何您想要的內容,從而使您的測試更加清晰穩定。 – mrfreester

回答

0

基本上,當您嘗試在頁面上不存在的東西上點擊或發送鍵時,Selenium會爆炸。
(我確定有一個默認的隱式等待,但我不確定它是什麼)。 基本上,您需要確定您希望測試在失敗之前等待事情的靈活程度。我希望這有幫助。

明確等待例如:

@Test 
public void testGoogleSearch() { 
    driver.get("http://duckduckgo.com"); 
    By searchInputBy = By.id("search_form_input_homepage"); 
    WebDriverWait wait = new WebDriverWait(driver, 10); 
    wait.until(ExpectedConditions.visibilityOfElementLocated(searchInputBy)); 
    driver.findElement(searchInputBy).sendKeys("Hello World"); 
    driver.findElement(By.id("search_button_homepage")).click(); 
    wait = new WebDriverWait(driver, 10); 
    By imagesBy = By.linkText("Images"); 
    wait.until(ExpectedConditions.elementToBeClickable(imagesBy)); 
    driver.findElement(imagesBy).click(); 
} 

隱等待例如:

@Test 
public void testGoogleSearch() { 
    driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS) ; 
    driver.get("http://duckduckgo.com"); 
    driver.findElement(By.id("search_form_input_homepage")).sendKeys("Hello World"); 
    driver.findElement(By.id("search_button_homepage")).click(); 
    driver.findElement(By.linkText("Images")).click(); 
} 

您還可以使用流利的等待,給你更多的控制權明確等待的選項,這樣你可以告訴它忽略某些例外,但它們更加冗長。

我認爲創建一個靜態方法的庫來完成流暢等待的繁重工作是一種更好的可讀性,但是更容易出錯的方式來編寫測試。

FluentWait Javadoc

另外一個great answer中更詳細說明的等待。

+0

你有沒有試過你的例子?隱式等待不適用於Safari。明確的等待不應該是必須的(對於所有瀏覽器_except_ Safari,再次不需要),因爲Selenium應該在每個步驟之前等待頁面加載完成。 – Roxy

+0

我只是看着我的代碼,並意識到我忘了傳遞它的位置參數等待。現在應該工作。 –

0

根本原因是您的代碼不會等待搜索結果。您使用WebDriverWait以及ExpectedConditions等待images鏈接。看下面的例子。

@Test 
public void testGoogleSearch() { 
    driver.get("http://duckduckgo.com"); 
    driver.findElement(By.id("search_form_input_homepage")).sendKeys("Hello World"); 
    driver.findElement(By.id("search_button_homepage")).click(); 
    WebDriverWait waiter = new WebDriverWait(driver,20); 
    WebElement imagesLink = waiter.until(ExpectedConditions.elementToBeClickable(By.linkText("Images"))); 
    imagesLink.click(); 
}