首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >始终等待页面在PageObjects上加载

始终等待页面在PageObjects上加载
EN

Stack Overflow用户
提问于 2019-07-26 16:52:24
回答 1查看 1.1K关注 0票数 2

因此,我只是在创建一个简单的selenium/JBehave代码时,出现了一个问题。

我将首先发布简化的代码,然后解释我的问题是什么。

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

AbstractPage.java

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
@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 amountToDeposit(@Named("strType") String strType) {
        pageObject.sendKeysWebElement2(strType);
    }
}

现在我的问题是:

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

例如,根据我需要等待的内容,我将为每个waitPageLoad()提供不同的pageObject。在本例中,我会等待webElement1和webElement2可见。

selenium有类似于:@AlwaysWait的东西吗?我可以在方法之前使用它,并且每次使用页面对象时都会调用它(同样,没有在步骤中调用它)吗?还是每次使用页面对象时都要调用一个方法的符号?

示例:

代码语言:javascript
复制
@AlwaysWait
public void waitPageObjectLoad() {
    WebDriverWait wait = new WebDriverWait(webDriverProvider.get(), 30);        
    wait.until(ExpectedConditions.visibilityOfAllElements(webElement1, webElement2));
}

希望我能让自己明白,谢谢。

PS:询问一下,我知道您可以以某种方式使用java反射框架来完成它,但是我想知道您是否可以只使用selenium来完成它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-26 18:28:30

--这是您学习如何热爱多态性和代理模式的地方.

创建一个实现WebDriver接口的新的具体类,名为LazyWebDriver。创建另外两个类来延迟加载web元素: LazyWebElement和LazyWebElementList。

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

现在,您只需使用LazyWebDriver,就好像它是任何其他web驱动程序一样。使用标准WebDriver接口查找元素总是要等待一定的时间:

代码语言:javascript
复制
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");

LazyWebDriver类

代码语言:javascript
复制
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(...)
}

LazyWebElement类

代码语言:javascript
复制
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()
}

LazyWebElementList类

代码语言:javascript
复制
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中获取webDriverProvider对象。您可以继续使用它,除非web驱动程序提供程序将LazyWebDriver强制转换返回到WebDriver接口。您的其余代码仍然完全不知道LazyWebDriver、LazyWebElement和LazyWebElementList甚至存在。这应该很容易插入到您现有的测试代码中。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57224220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档