在 RobotFramework 中扩展 selenium2library WebElement

Extending selenium2library WebElement in RobotFramework

我是 RobotFramework 的新手(实际上是为一个新的测试自动化项目评估它)。

过去,我总是使用 Java 和页面对象创建自己的小框架,但是这次我想知道是否可以使用现有框架。我正在评估 Spock 和机器人框架。

我的要求是测试 Web 应用程序、windows 对象和移动应用程序,因此 Robot 绝对比 Spock 有优势。此外,我更喜欢 Python 而不是 Groovy 任何一天。

我通常使用以下代码在我的框架中扩展 WebElement。我想知道是否可以在 Robot Framework 中做这样的事情。

//importing webdriver and other selenium libraries
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.internal.Coordinates;
import org.openqa.selenium.internal.Locatable;
import org.openqa.selenium.internal.WrapsElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

//interface that will be implemented by my custom web element
interface MyElement extends WebElement, WrapsElement, Locatable {

}

//my custom web element class
public class MyWebElement implements MyElement {

    private WebElement element;

    //private constructor for my web element class
    private MyWebElement(WebElement element) {
        this.element = element;
    }

    //public factory method for my web element class
    public static MyWebElement getInstance(By by) {
        WebElement element = MyWebDriver.getInstance().findElement(by);
        MyWebElement myWebElement = new MyWebElement(element);
        return myWebElement;
    }

    //overriding WebElement method click
    @Override
    public void click() {
        waitUntilClickable();
        element.click();
    }

    //adding method waitUntilClickable to my web element
    public MyWebElement waitUntilClickable() {
        return waitUntilClickable(MyWebDriver.getTimeoutElementInMilliseconds(),
                MyWebDriver.getPollingElementInMilliseconds());
    }

    //adding helper method to implement waitUntilClickable
    public MyWebElement waitUntilClickable(long timeOutInMilliseconds,
            long pollingIntervalInMilliseconds) {
        Wait<WebDriver> wait = new FluentWait<WebDriver>(MyWebDriver.getInstance())
                .withTimeout(timeOutInMilliseconds, TimeUnit.MILLISECONDS)
                .pollingEvery(pollingIntervalInMilliseconds, TimeUnit.MILLISECONDS);
        wait.until(ExpectedConditions.elementToBeClickable(element));
        return this;
    }
   //other additional and overriding methods
   //.........................
   //.........................

Robot Framework 到目前为止看起来不错,我也喜欢 python.. 但是我不知道我是否能够扩展像 selenium2library 这样的库来拥有我自己的自定义方法,就像我以前那样在上面的例子中做 java。

Python and Java are possible. However, I think that using the already available keywords 中编写扩展并通过使用现有功能制作自定义关键字来创建测试逻辑是我们大多数人创建测试用例的方式。

你可以,但我不确定它能为机器人框架提供什么价值。有关如何子类化库 and/or 以访问实际 webdriver 对象的示例,请参阅此问题的答案:Pass existing Webdriver object to custom Python library for Robot Framework

但是,使用 robot 的全部意义在于您没有直接调用 webdriver 函数。您当然可以覆盖这些方法(在 python 中称为 "monkeypatching")并且关键字将使用您的修补函数,但这并不是真正必要的。当您使用机器人时,您不应该直接与网络元素交互。

使用机器人框架,您应该编写更抽象的测试。例如:

*** Test Cases ***
| Login with valid credentials
| | Go to page | LoginPage
| | Enter the username | valid_user@example.com
| | Enter the password | letmein!
| | Click the login button
| | The current page should be | DashboardPage

注意测试是如何完全不使用网络元素的。它使用高级关键字,无需直接与 Web 元素交互、添加等待等。测试编写者与页面的实际实现完全隔离,因此他们可以专注于测试本身的逻辑。

当然,robot是一个通用的框架,不提供这样的关键字。它提供了通用关键字("go to page"、"click button" 等),但这并不是机器人框架真正强大的地方。真正的强大来自自定义页面特定的库。

在您的示例中,您展示了重写 click 方法,以便您可以添加显式等待。使用机器人,您可以在任何有意义的地方将等待构建到关键字本身,而不是覆盖该方法。

例如,"Click the login button" 的实现可能如下所示:

def click_login_button(self):
    with self._wait_for_page_refresh():
        WebDriverWait(self.browser, 10).until(
            lambda *args: button_element.element_to_be_clickable((By.ID, locator.login_button))
        )
        self.browser.find_element_by_id(locator.login_button).click()

在这个例子中,我们已经处理好等待元素可点击,我们点击它,然后我们等待页面刷新后再返回。请注意,在关键字本身中,您如何拥有 python 和 selenium 的全部功能,即使在测试用例级别可以看到其中的 none 。


注意:这些例子大致是基于我写的一个用robot实现页面对象模式的库。有关该库的更多信息,请参阅此博客 post:Robot Framework Page objects