2014-10-11 44 views

回答

1

這實際上是Selenium的默認行爲 - 在進入下一行代碼之前它會等到所有請求都完成爲止。

+0

沒錯。這個答案應該被接受。 – 2014-10-11 03:39:45

+0

但它不包括JavaScript和jQuery等? – JoriO 2014-10-11 07:32:36

+4

答案有點簡單。雖然大部分是正確的,但它掩蓋了許多微妙之處。有更好的答案,我會非常失望地看到這個成爲得分最高的答案。 – JimEvans 2014-10-11 12:31:36

0

driver.manage.implicitlywait(3,TimeUnit.Seconds)將hep。

9

最大的問題是,即使是大多數用戶,也不存在通用的,通用的解決方案。 「當我的頁面完成加載時」的概念在今天動態的,AJAX沉重的,JavaScript依賴的網站中幾乎變得毫無意義。人們可以等待瀏覽器確定網絡流量已完成,但這並不考慮JavaScript執行。人們可以將「complete」定義爲該頁面的onload事件已被觸發,但忽略了使用setTimeout()的頁面的可能性。此外,這些定義中沒有一個將幀或iframe考慮在內。

當談到硒時,有幾個因素需要考慮。請記住,Selenium RC API已有10年曆史。在設計和開發時,典型網頁的體系結構使得waitForPageToLoad等實用方法成爲可能。另一方面,WebDriver API認識到當前的現實。單獨的驅動程序實現通常會嘗試在明確的頁面導航期間等待頁面加載(例如,driver.get()),但是這種等待將是「盡力而爲」的,並且是而不是的保證。請注意,由用戶交互導致的導航(例如,element.click())不太可能完全等待,因爲這種交互是異步的,並且因此具有競爭條件。

WebDriver的正確方法是等待要與之交互的元素出現在後續頁面上。這最好用WebDriverWait或類似的結構完成。您可能會在支持庫中找到其他一些結構,主要是那些處理頁面對象模式的結構。您也可以嘗試在您的驅動程序實例中設置隱式等待超時,但我相信使用它會掩蓋意圖。

1

有一個通過Selenium支持庫SlowLoadableComponent提供的設計模式,可以做你想做的事:https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/support/ui/SlowLoadableComponent.html。要點是你寫你的頁面對象到extendSlowLoadableComponent。你將不得不在SlowLoadableComponent兩個abstract方法的實現:load()isLoaded()

isLoaded()方法應該檢查你需要考慮你的頁面「加載」的一切。 load()方法執行加載頁面對象所需的操作。您爲頁面對象指定加載超時(我通過頁面對象的構造函數執行此操作)。當您在從SlowLoadableComponent繼承的頁面對象上調用get()方法時,它將調用isLoaded()。如果你的頁面對象沒有加載,它會調用load()加載你的頁面對象。它將繼續執行此操作,直到您的頁面對象被加載,或者直到您的超時過期。

但是,您必須自己定義頁面對象加載的含義。 Selenium無法確定您的特定頁面對象是否已加載,因爲這些判斷對上下文敏感。例如,考慮表示Web應用程序的登錄頁面的頁面對象。如果用戶名和密碼輸入文本框和提交登錄按鈕都可見,則它被「加載」。這不適用於表示網絡應用程序中某個其他頁面的頁面對象。您必須爲任何給定的頁面對象定製「已加載」條件。

這是一個簡單的例子。基本抽象裝載對象:

import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.support.PageFactory; 
import org.openqa.selenium.support.ui.SlowLoadableComponent; 
import org.openqa.selenium.support.ui.SystemClock; 

public abstract class AbstractLoadableComponent<T extends AbstractLoadableComponent<T>> extends SlowLoadableComponent<T> { 

    public static final int DEFAULT_TIMEOUT_IN_SECONDS = 30; 
    private final WebDriver driver; 
    private final int timeoutInSeconds; 

    public AbstractLoadableComponent(final WebDriver driver, final int timeoutInSeconds) { 
     super(new SystemClock(), timeoutInSeconds); 

     this.driver = driver; 
     this.timeoutInSeconds = timeoutInSeconds; 
     this.load(); 
    } 

    public final WebDriver getDriver() { 
     return driver; 
    } 

    public final int getTimeoutInSeconds() { 
     return timeoutInSeconds; 
    } 

    @Override 
    protected void load() { 
     PageFactory.initElements(getDriver(), this); 
    } 
} 

基本抽象頁面對象:一個登錄頁面

import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.support.ui.SlowLoadableComponent; 

public abstract class AbstractPage<T extends AbstractPage<T>> extends AbstractLoadableComponent<T> { 

    private final String url; 

    public AbstractPage(final WebDriver driver) { 
     this(driver, driver.getCurrentUrl(), DEFAULT_TIMEOUT_IN_SECONDS); 
    } 

    public AbstractPage(final WebDriver driver, final String url) { 
     this(driver, url, DEFAULT_TIMEOUT_IN_SECONDS); 
    } 

    public AbstractPage(final WebDriver driver, final String url, final int timeoutInSeconds) { 
     super(driver, timeoutInSeconds); 
     this.url = url; 
    } 

    public final String getUrl() { 
     return url; 
    } 

    @Override 
    protected void load() { 
     super.load(); 

     if(url != null) { 
      getDriver().get(url); 
     } 
    } 
} 

基礎混凝土頁面對象類:

import org.openqa.selenium.NoSuchElementException; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 
import org.openqa.selenium.support.How; 

import static org.testng.Assert.assertTrue; 

public final class LoginPage extends AbstractPage<LoginPage> { 

    @FindBy(how = How.ID, using = "username") 
    private WebElement usernameBox; 

    @FindBy(how = How.ID, using = "password") 
    private WebElement passwordBox; 

    @FindBy(how = How.NAME, using = "login") 
    private WebElement loginButton; 

    public LoginPage(final WebDriver driver) { 
     this(driver, driver.getCurrentUrl(), DEFAULT_TIMEOUT_IN_SECONDS); 
    } 

    public LoginPage(final WebDriver driver, final String url) { 
     this(driver, url, DEFAULT_TIMEOUT_IN_SECONDS); 
    } 

    public LoginPage(final WebDriver driver, final String url, final int timeoutInSeconds) { 
     super(driver, url, timeoutInSeconds); 
    } 

    @Override 
    protected final void isLoaded() throws Error { 
     try { 
      assertTrue(usernameBox.isDisplayed(), "Username text box is not displayed"); 
      assertTrue(passwordBox.isDisplayed(), "Password text box is not displayed"); 
      assertTrue(loginButton.isDisplayed(), "Login button is not displayed"); 
     } catch(NoSuchElementException nsee) { 
      throw new Error(nsee); 
     } 
    } 
} 
相關問題