【问题标题】:How to avoid multiple driver.findElement calls on the same web element?如何避免对同一个 Web 元素的多个 driver.findElement 调用?
【发布时间】:2013-08-25 02:00:58
【问题描述】:

我正在为我的 selenium webdriver+TestNG 框架使用 PageObject 模式。
在我的 pageObject 类中,我有多种方法,我使用 driver.findElement 来查找同一页面上存在的相同 web 元素。
例如:

 public class HomePage extends BasePage {
        private WebElement searchField;
        private String searchFieldLocator;


        HomePage(WebDriver driverFromTest, CustomLogger loggerFromTest,
                HashMap<String, String> testDataMapFromTest)
        {
            super(driverFromTest, loggerFromTest, testDataMapFromTest);
            searchFieldLocator = testDataMap.get("searchFieldLocator");

        }


        public void method1()
      {

        searchField = driver.findElement(By.cssSelector(searchFieldLocator));
        searchField.sendKeys("foo");

      }


      public void method2()
      {
         searchField = driver.findElement(By.cssSelector(searchFieldLocator));
         searchField.sendKeys("bar");
      }



我的问题是:
1. 如何避免在同一个 WebElement 变量上多次使用 driver.findElement。我想要一种方法,一旦我找到 webelement,我将在任何其他方法中使用该变量,而不使用 driver.findElement。我已阅读有关 PageFactory 的信息,您可以在其中使用 @FindBy(how = How.NAME, using = "locatorstring") 和 @CacheLookup 注释。这是我需要的吗? CacheLookup 是否只使用一次 driver.findElement 并重复使用该引用?

2. 其次,当你对同一个 web 元素执行太多 driver.findElements 时,它是否会占用大量内存?这是我不需要担心的微优化吗?

我想到了一种避免在同一个 web 元素上执行 driver.findElement 的方法,方法是编写如下方法:

 protected WebElement getWebElement(By by, String elementName) {
        WebElement element;

        if(webElementMap.get(elementName)==null)
        {
           element = driver.findElement(by);
           webElementMap.put(elementName, element);
        }
        else
            element = webElementMap.get(elementName);

        return element;

    }

这是正确的做法吗?

【问题讨论】:

    标签: webdriver selenium-webdriver ui-automation


    【解决方案1】:

    是的

    @CacheLookup 只使用一次 driver.findElement 并重复使用该引用。

    请注意,尽管您可能会遇到 StaleElementReferenceException 的情况

    【讨论】:

    • 好的,我的第二个问题呢??
    • 另外,那么只对网页上的静态元素而不是动态元素使用 FindBy 和 CacheLookup 会更好吗?
    • 关于它是内存密集型的,您的测试使用的内存量是否有任何问题(我不能说我曾经有过,所以我从未尝试过测量它)。我个人不打扰@CacheLookup,但我建议在静态元素上使用它,如果你要使用它的话。
    • 我的测试套件非常大,包含大量的 PageObject 类。我有一个 webdriver 在 driver.findElement 调用期间随机失败的问题,所以我想我应该检查是否有太多 driver.findElement 调用导致它。我也没有测量内存使用量。
    • 定义随机失败。目前我有一个非常大的测试框架,其中包含很多页面对象类,但是 findElement 调用没有问题。在开始优化内存使用之前,请检查这确实是一个问题,引用 Donald Knuth “过早的优化是万恶之源”
    【解决方案2】:

    使用诸如 Saucelabs 之类的网格提供程序时,多次调用可能会成为问题。

    每个 Webdriver 命令都会导致一次 API 调用,因此以下将进行两次 API 调用;

    searchField = driver.findElement(By.cssSelector(searchFieldLocator));
    searchField.sendKeys("foo");
    

    对 Grid 的请求将比使用特定驱动程序(例如 ChromeDriver)慢很多,因此在编写可能使用 Grid 的测试时必须考虑这一点。缓存对象是实现这一点的方法。

    但是,如果你缓存对象,你很可能会遇到StaleObject 问题,所以你引用 Kenny Rogers 的话;

    “你必须知道什么时候拿着它们,知道什么时候折叠它们”

    我个人远离@FindBy 和@CacheLookup 注释,因为我想控制缓存策略

    【讨论】:

    • 所以可以多次调用 driver.findElements,而不是使用 cacheLookup?截至目前,我没有使用硒网格。
    • 是的,如果您一遍又一遍地创建对象,我认为您不会遇到任何性能问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 1970-01-01
    • 2022-11-06
    • 2019-01-25
    • 2020-05-31
    • 1970-01-01
    相关资源
    最近更新 更多