在Selenium中,"wait until the page loading stops"的命令是什么



如何让WebDriver等待页面加载完全停止。

也就是说,它等待并检查整个页面是否已加载,然后只有它继续执行下一行。

最大的问题是,没有一个通用的、一刀切的解决方案可以适用于大多数用户。"我的页面何时加载完成"的概念在当今动态的、AJAX密集的、依赖JavaScript的网络中几乎毫无意义。可以等待浏览器确定网络流量是否完成,但这不考虑JavaScript的执行。可以将"完成"定义为页面的onload事件已触发,但这忽略了页面使用setTimeout()的可能性。此外,这些定义都没有考虑框架或iframe。

当谈到硒时,有几个因素需要考虑。请记住,Selenium RC API已有10年历史。在设计和开发时,典型网页的体系结构使waitForPageToLoad这样的方法变得实用。另一方面,WebDriver API认识到了当前的现实。单独的驱动程序实现通常会在显式页面导航(例如driver.get())期间尝试等待页面加载,但这种等待将是"最大的努力",而不是的保证。请注意,由用户交互(例如element.click())引起的导航不太可能完全等待,因为这种交互是异步的,因此固有地具有竞争条件。

WebDriver的正确方法是等待要与之交互的元素出现在后续页面上。这最好用WebDriverWait或类似的构造来实现。您可能会在支持库中找到一些其他构造,主要是在那些处理页面对象模式的构造中。您也可以尝试在驱动程序实例中设置隐含的等待超时,但我认为使用它会模糊意图。

这实际上是Selenium的默认行为——它等待所有请求完成后再执行下一行代码。

Selenium支持库SlowLoadableComponent提供了一种设计模式,可以实现您想要的功能:https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/support/ui/SlowLoadableComponent.html.要点是将页面对象写入extend SlowLoadableComponent。您必须在SlowLoadableComponent中提供两种abstract方法的实现:load()isLoaded()

isLoaded()方法应该检查所有需要考虑页面"已加载"的内容。load()方法执行加载页面对象所需的操作。您可以为页面对象指定加载超时(我通过页面对象的构造函数来执行此操作)。当您在页面对象上调用从SlowLoadableComponent继承的get()方法时,它将调用isLoaded()。如果没有加载页面对象,它将调用load()来加载页面对象。它将继续执行此操作,直到加载页面对象或超时为止。

但是,您必须自己定义要加载页面对象的含义。Selenium没有现成的方法来确定是否加载了特定的页面对象,因为这些确定是上下文敏感的。例如,考虑一个代表web应用程序登录页面的页面对象。如果用户名和密码输入文本框以及提交登录按钮可见,则它被"加载"。这不适用于表示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);
        }
    }
}

driver.manage.inimplicitlwait(3,TimeUnit.Seconds)将执行。

最新更新