如何将 Selenium 的 PageFactory 注释与动态加载的元素一起使用?

软件测试 自动化测试 测试设计 页面对象
2022-01-24 20:34:56

我正在根据页面对象设计模式利用Seleniums 的 annotations重写一些 Selenium 测试。我的问题是我有一些 htmlselect元素,其option元素是动态加载的。这些不能在selects 的同时可用。

原始代码如下所示:

public void fillinForm() {
    // Fill-in some fields ...

    // Select dynamic loaded option
    String optionXpath = "//*[@id='field']/option[text()='Software engineering']";
    waitForElement(driver, By.xpath(optionXpath), SHORT_TIMEOUT_S);
    driver.findElement(By.xpath(optionXpath)).click();

    // Fill-in more fields, etc ...
}

// Selenium wait
public static void waitForElement(WebDriver driver, By by, int timeout) {
    // implementation
}

新代码变成了这样的东西:

public void setUp() {
    page = PageFactory.initElements(driver, Page.class);
}

public void fillinForm() {
    page.setField("Software engineering");
}

public class Page {
    private webElement field;

    public Page setField(String byText) {
        field.click();
        String optionXpath = String.format("./option[text()='%s']", byText);
        field.findElement(By.xpath(optionXpath)).click();
        return this;
    }
}

如果我想在新代码中实现等待,我必须使用option包含 的 xpath 的 xpath select,从而失去使用注释来简化代码的优势:

public void fillinForm() {
    page.setField("Software engineering");
}

public class Page {
    private webElement field;

    public Page setField(String byText) {
        field.click();
        // Note that I'm now explicitly writing "field", exactly what I wanted
        // to save using annotations and the PageFactory
        String optionXpath = String.format("//select[@id='%s']/option[text()='%s']",
            "field", byText);
        field.findElement(By.xpath(optionXpath)).click();
        return this;
    }
}

是否有任何注释可以用来等到加载选项,还是我使用错了?

1个回答

WebDriverWait上花了更多时间之后,我得到了一些更好的东西:

客户端代码:

/** Page Object. */
public class Page {
    private WebElement mySelect;

    public Page setMySelect(String optionText) {
        String optXpath = String.format("./option[text()='%s']", optionText);
        mySelect.click();
        waitForOption(driver,mySelect, By.xpath(optXpath), 10)
            .click();
    }
}

实用程序库:

public class Util {

    /**
     * Waits until the option targeted by <tt>byOption</tt> is available.
     *
     * @param select parent element of the option to wait for
     * @param byOption selector (relative to the <tt>select</tt>). It will be
     *             searched calling <tt>select.findElement(byOption)</tt>
     * @return option element
     */
    public static WebElement waitForOption(
            WebDriver driver, WebElement select, By byOption, int seconds) {
        Wait<WebDriver> wait = new WebDriverWait(driver, seconds);
        return wait.until(new OptionAvailable(select, byOption));

    }

    public static class OptionAvailable
            implements ExpectedCondition<WebElement> {
        private WebElement select;
        private By byOption;

        public OptionAvailable(WebElement select, By byOption) {
            this.select = select;
            this.byOption = byOption;
        }

        @Override
        public WebElement apply(WebDriver input) {
            return select.findElement(byOption);
        }
    }
}

请注意,使用这种方法(aBy表示选项),我们可以将选项支持为文本或值。