如何在 PageFactory 中使用 FluentWait [重复]

Posted

技术标签:

【中文标题】如何在 PageFactory 中使用 FluentWait [重复]【英文标题】:How to use FluentWait in PageFactory [duplicate] 【发布时间】:2019-09-20 02:52:12 【问题描述】:

隐式和显式等待不起作用。 如何解决? 如何在PageFactory中使用FluentWait,这样在测试中就不需要使用定位器了。 尽量不要使用 Thread.sleep。

使用的工具:Selenium、TestNG、WebDriverManager 网站是在 AngularJS 上制作的。

public class LoginPage 

    private WebDriver driver;

    public StudioMenuPage(WebDriver driver) 
        this.driver = driver;
        PageFactory.initElements(driver, this);
    

    @FindBy(xpath = "//div[@class='login']")
    private WebElement loginButton;

    public WebElement getLoginButton() 
        return loginButton;
    



public class TestBase 
public static WebDriver driver = null;

@BeforeTest()
public void initialize() 
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
options.addArguments("--no-sandbox");
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
    



public class LoginTest extends TestBase 

LoginPage loginPage;    

@Test
private void makeLogin() 

loginPage = new LoginPage(driver);

// Does not work with Implicit Wait:
/* 
loginPage.getLoginButton().click;
*/


// Works with Thread.sleep:
/* 
Thread.sleep(4000);
loginPage.getLoginButton().click;
*/

// Does not work with Explicit Wait:
/* 
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(loginPage.getLoginButton()));
loginPage.getLoginButton().click;
*/

// Works with FluentWait:
/*  
new FluentWait<>(driver).withTimeout(Duration.ofSeconds(5)).pollingEvery(Duration.ofMillis(500))
    .ignoring(WebDriverException.class)
    .until(d -> 
                    WebElement el = d.findElement(By.xpath("//div[@class='login']"));
                    el.click();
                    return el;
                );
*/

如果使用隐式和显式等待者,则会出现以下错误:

org.openqa.selenium.WebDriverException: unknown error: Element <div class="login">...</div> is not clickable at point (225, 334). Other element would receive the click: <div id="cdk-overlay-0" class="cdk-overlay-pane" dir="ltr" style="pointer-events: auto; top: 316px; left: 201.5px;">...</div>
  (Session info: headless chrome=73.0.3683.86)
  (Driver info: chromedriver=2.46.628411 (3324f4c8be9ff2f70a05a30ebc72ffb013e1a71e),platform=Mac OS X 10.14.4 x86_64) (WARNING: The server did not provide any stacktrace information)

【问题讨论】:

如果您阅读了错误消息,它会准确地告诉您发生了什么。您试图点击&lt;div class="login"&gt;,但&lt;div id="cdk-overlay-0" ...&gt; 挡住了路。您需要先处理覆盖。如果没有 URL 或更多描述,我们无法告诉您如何针对您的特定情况执行此操作……可能是等待覆盖层可见、不可见,然后单击您的元素,或者它可能会处理一个弹出窗口已经出现(关闭它等)。您需要进行更多研究,然后返回并使用其他详细信息编辑您的问题。 哦...声称Implicit and Explicit wait don't work 有点傻。其他人都可以很好地使用它们,因此它们可以正常工作,而您只是在错误地使用它们。 【参考方案1】:

首先:我们不能混合隐式和显式等待!这样做可能会导致无法预料的等待时间。

建议您将 PageFactoryAjaxElementLocatorFactory 一起使用,这将等待每个元素 ANYTIME 访问指定的秒数,并且忽略 AjaxElementLocatorFactory strong>CacheLookup 标签。

PageFactory.initElements(new AjaxElementLocatorFactory(driver, 15), this);

如果在给定的时间间隔内没有找到该元素,则会抛出NoSuchElementException异常。

下面的例子展示了如何在页面工厂中实现 FluentWait -

protected synchronized void waitForElementVisibilityAndClick(WebElement element, int timeOut, String elementName) 
    protected static Wait<WebDriver> wait = null;
    try 
        wait = new FluentWait<WebDriver>((WebDriver) driver).withTimeout(timeOut, TimeUnit.SECONDS).pollingEvery(1,
                TimeUnit.SECONDS);
        wait.until(ExpectedConditions.visibilityOf(element));
        element.click();
    catch(Exception e) 
    

【讨论】:

以上是关于如何在 PageFactory 中使用 FluentWait [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Selenium 和 Java 通过 PageFactory 等待元素不可见

Selenium:使用PageFactory实现PagaObject设计模式

一篇文章学会PageFactory模式

seleniumPage Object模式(使用selenium的PageFactory)

Selenium的PageFactory & PageObject 在大型项目中的应用

转在Python中实现PageFactory模式