等待元素 - WebDriver - PageObject模式 [英] Wait for element - WebDriver - PageObject pattern

查看:201
本文介绍了等待元素 - WebDriver - PageObject模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只要我使用PageObject模式,我就想知道在动态页面上应该在哪里等待元素。假设我们有测试方法和pageObject类。我应该做什么(在测试方法中):

As long as I use PageObject pattern I wondered where should I wait for element on dynamic pages. Assuming we have test method and pageObject class. Should I do something like (in test method):


  1. 点击按钮

  2. 等待元素显示

  3. 验证元素(包含例如方法isElementDisplayed())

或也许有其他好的做法等待元素?也许我们应该等待PageObject.class中的方法isElementDisplayed中的元素?

Or maybe there is other good practice to wait for the element? Maybe we should wait for element in method isElementDisplayed which is in PageObject.class?

推荐答案

你应该等待页面对象中的元素类,不在测试类中,因为你的元素应该在页面对象类中定义,测试类应该不知道任何元素,选择器或类似的东西。测试,恕我直言,应该只包含描述测试流程的方法调用链,所有与网站和底层DOM的交互都应该在Page Object类中进行。

You should wait for elements in your page object class, not in test class, because your elements should be defined in page object class, test class should know nothing of any elements, selectors or similar. Tests, IMHO, should contain only chains of method calls that describe the test flow, all the interaction with the website and underlying DOM should take place in Page Object class.

所以等待某个元素出现的过于冗长的方法可能是这样的:

So an overly verbose method to wait for some element to appear could be something like:

private final By yourElement = By.id("id");
@Override
public void isLoaded() throws Error {
    new FluentWait<WebDriver>(driver)
            .withTimeout(60, TimeUnit.SECONDS)
            .pollingEvery(1, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class)
            .ignoring(StaleElementReferenceException.class)
            .until(new Function<WebDriver, Boolean>() {
                @NotNull
                @Override
                public Boolean apply(WebDriver webDriver) {
                    WebElement element = driver.findElement(yourElement);
                    return element != null && element.isDisplayed();
                }
            });
}

简单来说,该函数如果轮询DOM 60秒(每1个)第二)看看,如果元素存在于DOM中并且它是可见的(意味着高度和大于1px)。如果该元素存在(并显示),则该函数返回找到的元素并停止轮询(尽管 isLoaded()方法在此特定情况下不返回该元素)。

In plain words, the function if polling the DOM for 60 secs (every 1 second) to see, if the element exists in DOM and it is visible (means has height and witdh greater than 1px). If the element exists (and is displayed), the function returns the found element and stops the polling (although isLoaded() method does not return the element in this particular case).

忽略 NoSuchElementException 是有道理的,可以通过 findElement 方法,如果找不到该元素, StaleElementException ,表示对元素的引用现在是陈旧的 - 该元素不再出现在DOM上的页面。这通常意味着某些东西(最常见的是JS)修改了DOM并且引用不再有效,因此 WebDriver 需要再次查找它。

It makes sense to ignore NoSuchElementException which can be thrown by findElement method in case the element is not found, and StaleElementException, which indicates that a reference to an element is now "stale" - the element no longer appears on the DOM of the page. This usually means, that something (most commonly JS) has modified the DOM and the reference is no longer valid, hence the WebDriver needs to look it up again.

当然,更短的代码也可以使用,例如:

Of course shorter code would also to the trick, something like:

    new WebDriverWait(driver, 60)
            .until(ExpectedConditions.visibilityOf(someWebElement));

文档实际上相当不错。

编辑:回答评论:


好的,明白了。但是如果在点击一些
按钮之后元素出现怎么办?

OK, understood. But what if element is present after clicking on some button etc.?

让我们说你有一个场景,你在哪里有一个按钮,点击该按钮后会出现一个文本框,你想与之交互。

Lets say you have a scenario, where you have a button and after clicking that button a textbox appears and you want to interact with it.

public class PageObject extends LoadableComponent<PageObject>{

    public PageObject() throws Exception {
        driver = getWebDriver();
        PageFactory.initElements(driver, this);
        isLoaded();
    }
    private WebDriver driver = null;

    @FindBy(id = "yourButton")
    private WebElement button;

    @FindBy(id = "textBoxThatAppears")
    private WebElement txtBox;

    @Override
    public void isLoaded() throws Error {
        // Initial loading, called when creating the page object to make sure that the page is loaded to a state where it is ready to interact with us, in our case it means that button is present in DOM and visible.
        waitForVisibility(button);
    }

    private void waitForVisibility(WebElement element) throws Error{
           new WebDriverWait(driver, 60)
                .until(ExpectedConditions.visibilityOf(element));
    }

    public void clickButton(){
        button.click();

    }

    public void interactWithTextbox(String text){
        // Wait for txtBox to be visible, then send text
        waitForVisibility(txtBox);
        txtBox.sendKeys(text);

       // EDIT 27.04.14: 
       // Actually you should not do the assertion here or anywhere in 
       // the pageObject, because when reusing the method in some other test, you might
       // not want to assert, you might wonder that why wouldn't you assert some 
       // specific condition every time, but I would throw that question right back 
       // to you and ask: What is the point of checking the exact same thing over and 
       // over again. There are 2 things, firstly the assertion takes resources (and
       // that can become important when test suite grows, secondly your tests can 
       // simply start failing at the same point when one little condition is not as
       // it should be. Also, having the asserts in the test, makes the test more
       // readable and understandable for others.
         // end edit 27.04.14
        // Next line is no longer recommended by this answer.
         // assert that something happened that you expected.
    }

}

现在你的测试类:

public void TestClass {

     @Test
     public void testClickButtonAndInteractWithTextbox(){
         // Initiate the page object
         Pageobject po = new PageObject();
         po.clickButtonAndWaitForTextbox();
         po.interactWithTextbox("blabla");
         // edit 27.04.14
         assertSomethingGoodHappened();
     }
}

这篇关于等待元素 - WebDriver - PageObject模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆