简体   繁体   中英

How to avoid multiple driver.findElement calls on the same web element?

I am using PageObject pattern for my selenium webdriver+TestNG framework.
In my pageObject classes I have multiple methods where I am using driver.findElement to find the same webelement present on the same page.
For example:

 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");
      }



My questions are:
1. How can I avoid using driver.findElement on the same WebElement variables multiple times. I want a way where once I find the webelement, I'll just use the variable in any other method without using driver.findElement. I have read about PageFactory where you can use @FindBy(how = How.NAME, using = "locatorstring") with @CacheLookup annotation. Is it what I need? Does CacheLookup use driver.findElement only once and re-uses the reference?

2. Secondly, does it become memory intensive when you perform driver.findElements too many times for the same web-element? Is this micro-optimization that I don't need to worry about?

I thought of a way to avoid doing driver.findElement on the same web element by writing a method like this:

 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;

    }

Is this the right way to do it?

Yes

@CacheLookup does use driver.findElement only once and re-uses the reference.

Watch out though you may start coming accross StaleElementReferenceException's

Multiple calls can be a problem when using a Grid provider such as Saucelabs.

Each Webdriver command results in a API call so the following would make two API calls;

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

Requests to the Grid will be magnitudes slower then user a specific driver such as ChromeDriver so you have to consider this when writing tests which may potentially use Grid. Caching objects is way to achieve this.

However, if you cache objects, you are likely to hit StaleObject issues, so you to quote Kenny Rogers;

"You got to know when to hold 'em, know when to fold 'em"

I personally stay away from the @FindBy and @CacheLookup annotations as I want to have control of caching strategy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM