【问题标题】:@FindBy WebElements are not being initialised in a PageFactory/Page Object framework@FindBy WebElements 没有在 PageFactory/Page Object 框架中初始化
【发布时间】:2016-09-01 17:35:01
【问题描述】:

更新代码:

public class FlightBookingTest extends PageBase{

@Test(priority = 1)
@Parameters({"from", "to"})
public void searchForAPackage(String from, String to) throws InterruptedException {

    customerHomePage().selectDepartureAirport(from);
    customerHomePage().selectDestinationAirport(to);
    customerHomePage().selectStartDate();
    customerHomePage().submitSearchRequest();

    assertThat(searchResultsPage().checkPageTitle(), equalTo("Flight Results"));
}

页面对象:

public class CustomerHomePage extends PageBase {

@FindBy(how = How.XPATH, using = ".//* [@id='container']/div/div[3]/div/div[1]/div/h3")
public WebElement searchResults;  
//loads more locators

public CustomerHomePage(WebDriver driver) {
    this.driver = driver;
    driver.manage().window().maximize();
}

public void visit(String url){
    driver.get(baseURL);
}

public void selectDepartureAirport(String departureAirport) {
    click(whereFromDropdown);
    selectOption(departureAirport);
}

public void selectDestinationAirport(String destination) {
    click(destinationLocator);
    type(destination, destinationLocator);
    selectOption("(" + destination + ")");
}

public void selectFromDate() {
    type("15/07/2016", dateFromField);
}

public void submitSearchRequest() {
    click(submitSearchButton);
    waitForIsDisplayed(searchResults, 120);
}

public void selectStartDate() {
    click(dateFromField);
    click(nextMonthSelector);
    click(dayOfMonth);
}

页面库:

public class PageBase extends  TestBase {

public CustomerHomePage customerHomePage()
{
    return PageFactory.initElements(driver, CustomerHomePage.class);
}

测试基地:

public class TestBase implements Config {

public WebDriver driver;
//a bunch of methods to handle Driver instantiation and kill

//a bunch of Webdriver utility methods including:
public void click(WebElement element) {
    waitForIsDisplayed(element, 120);
    element.click();
}
 public Boolean waitForIsDisplayed(WebElement element, Integer... timeout) {
    try {
        waitFor(ExpectedConditions.visibilityOf(element),
                (timeout.length > 0 ? timeout[0] : null));
    } catch (org.openqa.selenium.TimeoutException exception) {
        return false;
    }
    return true;
}

private void waitFor(ExpectedCondition<WebElement> condition, Integer timeout) {
    timeout = timeout != null ? timeout : 5;
    WebDriverWait wait = new WebDriverWait(driver, timeout);
    wait.until(condition); //java.lang.reflect.UndeclaredThrowableException HERE...Caused by NoSuchElementException
}

看起来框架不尊重预期条件的等待 - 元素的可见性。我怀疑与“visibilityOf(element)”的实现以及@FindBy 初始化元素的方式有关

异常的堆栈跟踪:

java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy7.findElement(Unknown Source)
at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:69)
at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
at com.sun.proxy.$Proxy9.isDisplayed(Unknown Source)
at org.openqa.selenium.support.ui.ExpectedConditions.elementIfVisible(ExpectedConditions.java:302)
at org.openqa.selenium.support.ui.ExpectedConditions.access$100(ExpectedConditions.java:41)
at org.openqa.selenium.support.ui.ExpectedConditions$10.apply(ExpectedConditions.java:288)
at org.openqa.selenium.support.ui.ExpectedConditions$10.apply(ExpectedConditions.java:285)
at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:238)
at com.multicom.fabrix.framework.TestBase.waitFor(TestBase.java:152)
at com.multicom.fabrix.framework.TestBase.waitForIsDisplayed(TestBase.java:141)
at com.multicom.fabrix.pageobjects.CustomerHomePage.waitForResults(CustomerHomePage.java:75)
at com.multicom.fabrix.regressiontests.FlightBookingTest.searchForAPackage(FlightBookingTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:643)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:782)
at org.testng.TestRunner.run(TestRunner.java:632)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
at org.testng.SuiteRunner.run(SuiteRunner.java:268)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
at org.testng.TestNG.run(TestNG.java:1064)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:74)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.mycompany.mymodule.webdriver.WebDriverInvoker.invokeNormally(WebDriverInvoker.java:47)
at com.mycompany.mymodule.webdriver.WebDriverInvoker.invoke(WebDriverInvoker.java:38)
... 41 more

原因:org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":".//*[@id='container']/ div/div[3]/div/div[1]/div/h3"}

【问题讨论】:

    标签: java selenium pageobjects


    【解决方案1】:

    将您的 PageBase 类切换到下面。您之前初始化了代理但没有返回该实例,只是一个新对象。否则,您可以使用 'this' 而不是 'CustomerHomePage.class' 将 initElements 行粘贴到 CustomerHomePage 的构造函数中

    public class PageBase extends SeleniumBase {
    
    public CustomerHomePage customerHomePage()
    {
        return PageFactory.initElements(driver, CustomerHomePage.class);
    }
    

    【讨论】:

    • 谢谢。按说明工作
    • 现阶段我不太明白的是,为什么现在所有使用 FindBy 炸弹的方法都带有 NoSuchElementExceptions。当我使用断点进行调试时,测试运行良好。因此,FindBy 存在同步问题。是否 initElements 在 WebDriver 驱动到相关页面或页面区域之前尝试查找定位器?根据测试,我引用了几个不同的 PageObjects,所以一些 FindBy 可能会在页面加载之前尝试初始化?
    • 在哪里初始化 PageObjects 并不重要,因为 PageFactory.initElements 只为标有 @FindBy 注释的 WebElement 字段提供代理。但是当您访问这些字段时,对于 sendkeys 或 click 等方法,您必须确保浏览器在正确的页面上。您可以将当前 URL 与您想要的 PageObject 进行比较,或者查看 LoadableComponent 类。如果你得到 NoSuchElementExceptions 在调试模式下消失,那么你需要使用 WebDriverWait 和 ExpectedConditions 类来正确同步。
    • 谢谢。这是有道理的。我已经用当前的实现和抛出异常的细节更新了代码。不太清楚为什么我对“waitForIsDisplayed”的调用没有得到尊重 - 它是“searchResults”定位器无法找到,但它试图在该页面加载之前找到它。 SearchResultsPage 是一个单独的 PageObject
    • 您的 PageBase 类不正确。您正在返回新实例,而不是使用 PageFactory.initElements 调用的实例。
    【解决方案2】:

    @FindBy 中的变量名称是 drioDownLocator,而您传递的变量名称是 dropDownContainer。您的班级中还有WebElement 类型的其他变量吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多