【问题标题】:Always wait for the page to load on PageObjects始终等待页面加载到 PageObjects
【发布时间】:2019-07-26 16:52:24
【问题描述】:

所以,当出现问题时,我只是创建了一个简单的 selenium/JBehave 代码。

我会先贴出简化的代码,稍后再解释我的问题。

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

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 amountToDeposit(@Named("strType") String strType) {
        pageObject.sendKeysWebElement2(strType);
    }
}

现在我的问题是:

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

例如,我会为每个 pageObject 设置一个不同的 waitPageLoad(),这取决于我需要等待什么。 在这个例子中,我会等待 webElement1 和 webElement2 可见。

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

示例:

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

希望我让自己可以理解, 提前致谢。

PS:四处打听,我知道你可以使用 java 反射框架来做到这一点,但我想知道你是否可以只用 selenium 来做到这一点。

【问题讨论】:

  • 我昨天在 Geb 找这个。 :-/
  • @chrylis 你找到什么了吗?
  • 全局waiting 配置中有一个选项“总是在检查员处等待”,但页面内容没有。至少在 Geb 我可以说类似waitFor { rows }
  • 也许我也可以在 spring 上使用自定义注释,然后在我的页面对象中使用它.. 不是 spring 专家,但它似乎很合理
  • 在一般情况下,您不应该需要这个,因为 Selenium 等待页面在转换时加载。如果您有动态加载页面的某些部分(AJAX 等),您将需要这样做。如果是这种情况,您可以编写 waitForPageLoad() 方法,将其标记为私有,然后在您的页面构造函数中调用它,或者在方法导致页面(或部分页面)加载时根据需要调用它。

标签: java selenium selenium-webdriver bdd jbehave


【解决方案1】:

您可以在这里学习多态性和代理模式。

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

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

现在您只需像使用任何其他 Web 驱动程序一样使用 LazyWebDriver。使用标准 WebDriver 接口查找元素总是会等待一定的秒数:

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 类

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 类

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 类

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
}

我在您的代码示例中看到您从 webDriverProvider 获取 WebDriver 对象。您可以继续使用它,除非 Web 驱动程序提供程序将 LazyWebDriver 强制转换返回到 WebDriver 接口。您的其余代码仍然完全不知道 LazyWebDriver、LazyWebElement 和 LazyWebElementList 甚至存在。这应该很容易插入到您现有的测试代码中。

【讨论】:

    猜你喜欢
    • 2017-09-13
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2020-01-04
    • 2017-03-27
    • 1970-01-01
    相关资源
    最近更新 更多