2

I am using Java and Selenium Webdriver in order to test the functionalities of a single page web application.

For this reason, clearly, elements are injected and removed from the DOM dynamically.

I know I can wait for an element to be present in the DOM using similar code that is using WebDriverWait (very neat template I wrote slightly changing GitHub):

public void waitForElement() throws Exception {
    /*
    Inject the following snippet in any web page to test the method
    <button class="i-am-your-class" onclick="alert('Wow, you pressed the button!');">Press me</button>
     */
    System.setProperty("webdriver.gecko.driver", "C:\\Program Files (x86)\\Mozilla Firefox\\geckodriver.exe");
    WebDriver driver = getDriver();
    WebDriverWait wait = new WebDriverWait(driver, 10); // 10 can be reduced as per Test Specifications
    driver.get("http://www.google.com");
    WebElement response = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@class='i-am-your-class']")));
    response.click();
    System.out.println("*****************************************************************************");
    System.out.println(response);
    System.out.println(response.getText());

    driver.close();
}

What I would like to know is if this is also the more efficient way to obtain such result using an xpath.

I have been researching on Stackoverflow and several answers point in a similar direction but no answer is focused on efficiency / performances:

Thanks for your time and help.

Pitto
  • 8,229
  • 3
  • 42
  • 51
  • The measurement of _efficient way_ will a lot depend on the method `enterSearchTerm()` where possibly you have used an _xpath_ and if the _xpath_ is optimized or not. – undetected Selenium May 18 '18 at 13:29
  • Your suggestion makes sense, @DebanjanB. I've edited the answer with a more detailed example. – Pitto May 18 '18 at 14:27
  • @Pitto : Is it compulsory for you to use xpath ? or you can go ahead with any locator ? – cruisepandey May 18 '18 at 15:01
  • @cruisepandey XPath is preferred but I am looking for the most efficient way to locate a new element in the DOM (created by Angular / React / anything). So, if in your opinion XPath is not the way to go, I'd be happy to read your idea on the best way to obtain the result. – Pitto May 18 '18 at 15:12

2 Answers2

2

There are a couple of facts which you need to consider as follows :

  • WebDriverWait() for 100 shouldn't be a real-time waiter. Consider reducing it as per the Test Specifications. As an example, set it as 10 seconds :

    WebDriverWait wait = new WebDriverWait(driver, 10);
    
  • Moving forward as you are invoking click() method so instead of ExpectedConditions as visibilityOfElementLocated() method use elementToBeClickable() method as follows :

    WebElement response = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@class='i-am-your-class']")));
    
  • Optimize your xpath including the tagName as in By.xpath("//tagName[@class='i-am-your-class']"). As an example :

    By.xpath("//a[@class='i-am-your-class']")
    
  • Optimize your code to invoke click() as soon as the element is returned through WebDriverWait as follows :

    new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//a[@class='i-am-your-class']"))).click();
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thanks, great share and fuel for thought. Do you think it is a good idea to use WebDriverWait or it would be better to use FluentWait? – Pitto May 19 '18 at 10:23
  • 1
    @Pitto WebdriverWait is the tailored version of FluentWait. So stay with WebdriverWait until and unless you exactly need FluentWait – undetected Selenium May 19 '18 at 11:29
  • Sorry for disturbing one lest time but... Would this solution be better or it is the same? driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://www.google.com"); WebElement myDynamicElement = driver.findElement(By.id("i-am-your-id")); – Pitto May 19 '18 at 21:41
  • 1
    @Pitto As a beginner you may opt to start with `implicitlyWait()` and `thread.sleep()`. Of-coarse `thread.sleep()` degrades your _Test Performance_ and _implicitlyWait()_ may die in fire soon. Moving forward make a transition to the optimized solution of **WebDriverWait**. Feel free to ask any question. – undetected Selenium May 21 '18 at 06:45
  • 1
    You totally clarified all my doubts, @DebanjanB ! WebDriverWait is then the real way to go, as I supposed. Really thanks. – Pitto May 22 '18 at 09:51
1

I do not know for what reason you have said XPATH is preferred. I would like to add something about locators.

The XPATH you have written in your code can be easily replaced by a css selector. Here is the example.

div[class='i-am-your-class']  

Now the main question is why do you want to switch to different locators ?

  • more efficiency.
  • more fast as compared to xpath.
  • more reliable.
  • more performance.

You should always use locators in this order as suggested by Selenium contributors

  1. ID
  2. name
  3. className
  4. linkText
  5. partialLinkText
  6. tagName
  7. cssSelector
  8. XPath.

Note : Most of the time a cssSelector can replace Xpath, However Xpath has its own advantages which cssSelector do not provide.

For more reference you can go through this SO Link : Xpath vs Css selector

cruisepandey
  • 28,520
  • 6
  • 20
  • 38
  • Your CSS selector looks more like an XPath... ;). When you write any locator as `attribute='value'` that is an exact string match. That means that if the class isn't exactly and only `i-am-your-class` then it will not match. It would be better to write it as `div.i-am-your-class`. It's not only shorter and easier to read, it will match any `DIV` that contains that class but not restricted to only that class as a `class='value'` might. – JeffC May 18 '18 at 20:46
  • @JeffC : yeah sure I’ll take that ! ;) – cruisepandey May 19 '18 at 05:54