始终等待页面加载到PageObjects上

时间:2019-07-26 16:52:24

标签: java selenium selenium-webdriver bdd jbehave

所以,当出现问题时,我只是在创建一个简单的selenium / JBehave代码。 我将首先发布简化的代码,然后在以后解释我的问题。

因此,这里有一个简单的AbstractClass,它将在我的PageObjects上继承。此类仅包含等待页面上某些元素加载的方法。您可以在PageObject类中看到Im的使用方式(在那里添加了注释)。

AbstractPage.java

public abstract class AbstractPage {
    public void waitPageLoad() {
        WebDriverWait wait = new WebDriverWait(webDriverProvider.get(), 30);        
        wait.until(ExpectedConditions.visibilityOfAllElements(elementsToWait()));
    }

    protected List<WebElement> elementsToWait() {
        return null;
    }
}

PageObject.java

public class PageObject extends AbstractPage{
    @FindBy(id = "webElement1")
    private WebElement webElement1;

    @FindBy(id = "webElement2")
    private WebElement webElement2;

    public void clickWebElement1() {
        webElement1.click();
    }

    public void sendKeysWebElement2(String strKeys) {
        webElement2.sendKeys(strKeys);
    }

    //Note how im using the elementsToWait here
    @Override
    protected List<WebElement> elementsToWait() {
        return Arrays.asList(webElement1, webElement2);
    }
}

现在,在我的步骤中,如果要先等待页面加载然后执行所需的操作,则需要在步骤之一中从抽象类中调用“ waitPageLoad()”方法(或者可以肯定所有这些)。

PageObjectSteps.java

@Component
public class PageObjectSteps {

    private PageObject pageObject;

    @When("User wants to click on webElement1")
    public void accountToDeposit () {
        pageObject.waitPageLoad(); //Calling here just as an example
        pageObject.clickWebElement1();
    }

    @When("User wants to type on webElement2 '$strType'")
    public void ammountToDeposit(@Named("strType") String strType) {
        pageObject.sendKeysWebElement2(strType);
    }
}

现在我的问题是:

是否有一种方法可以在每次使用我的pageObject时都调用 waitPageLoad(),但没有在步骤中调用该方法?

例如,根据我需要等待的时间,每个pageObject都有一个不同的 waitPageLoad()。 在此示例中,我将等待webElement1和webElement2可见。

硒是否有类似的东西: @AlwaysWait ,在这里我可以在方法之前使用它,并且每次使用页面对象时都会调用它(再次,无需在步骤中调用它)?还是一种使每次使用页面对象都被调用的方法的符号?

示例:

@AlwaysWait
public void waitPageObjectLoad() {
    WebDriverWait wait = new WebDriverWait(webDriverProvider.get(), 30);        
    wait.until(ExpectedConditions.visibilityOfAllElements(webElement1, webElement2));
}

希望我能使自己易于理解, 预先感谢。

PS:到处问,我知道您可以通过某种方式使用java反射框架来做到这一点,但是我想知道您是否只能使用硒来做到这一点。

1 个答案:

答案 0 :(得分:0)

这是您学习多态和代理模式的地方。

创建一个新的具体类,以实现名为WebDriver的{​​{1}}接口。创建另外两个类以延迟加载Web元素:LazyWebElement和LazyWebElementList。

LazyWebDriver中的方法应返回LazyWebElement或LazyWebElementList对象,但这些方法的返回值应为WebElement或List。

现在,您就像使用其他任何Web驱动程序一样,仅使用LazyWebDriver。使用标准WebDriver界面查找元素将始终等待一定秒数:

LazyWebDriver

LazyWebDriver类

WebDriver driver = new ChromeDriver();
int secondsToWait = 15;
WebDriver lazyDriver = new LazyWebDriver(driver, secondsToWait);

// findElement(...) returns immediately
WebElement element = lazyDriver.findElement(By.id("foo"));

// Implicitly waits up to 15 seconds for the element
// to become visible before attempting to click on it
element.click();

// Returns immediately since the "wrapped" element
// has already been fetched after waiting.
String name = element.getAttribute("name");

LazyWebElement类

public class LazyWebDriver implements WebDriver {
    private WebDriver driver;

    public LazyWebDriver(WebDriver driver, int secondsToWait) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, secondsToWait);
    }

    public void close() {
        driver.close();
    }

    public WebElement findElement(By by) {
        return new LazyWebElement(driver, by, wait);
    }

    public List<WebElement> findElements(By by) {
        return new LazyWebElementList(driver, by, wait);
    }

    // ... other methods just call through to driver.foo(...)
}

LazyWebElementList类

public class LazyWebElement implements WebElement {
    private final WebDriver driver;
    private final WebDriverWait wait;
    private final By by;
    private WebElement element;

    public LazyWebElement(WebDriver driver, By by, WebDriverWait wait) {
        this.driver = driver;
        this.by = by;
        this.wait = wait;
    }

    private WebElement getElement() {
        if (element == null) {
            wait.until(ExpectedConditions.visibilityOfElementLocated(by));
            element = driver.findElement(by);
        }

        return element;
    }

    public void clear() {
        getElement().clear();
    }

    public void click() {
        getElement().click();
    }

    public String getAttribute(String attributeName) {
        return getElement().getAttribute(attributeName);
    }

    // Other methods in WebElement interface must first call getElement()
}

我在您的代码示例中看到,您正在从public class LazyWebElementList implements List<WebElement> { private final WebDriver driver; private final WebDriverWait wait; private final By by; private List<WebElement> elements; public LazyWebElementList(WebDriver driver, By by, WebDriverWait wait) { this.driver = driver; this.by = by; this.wait = wait; } private List<WebElement> getElements() { if (elements == null) { wait.until(ExpectedConditions.visibilityOfAllElementsLocated(by)); elements = driver.findElements(by); } return elements; } public boolean add(WebElement element) { getElements().add(element); } public void clear() { getElements().clear(); } // Other methods defined in List<E> interface must call getElements() first } 获取WebDriver对象。您可以继续使用它,除非Web驱动程序提供程序将LazyWebDriver强制类型转换返回到WebDriver界面。您的其余代码完全不知道LazyWebDriver,LazyWebElement和LazyWebElementList是否存在。这应该很容易插入到您现有的测试代码中。