How to speed up Java Selenium Script,with minimum

2020-01-29 21:09发布

问题:

I'm currently working on a java selenium Project, which is usually a small script where I have to check for each element for it's presence and based on that some actions are triggered but our main concern is time duration to finish the script.

Basically I have used each one from below in my script and ran the test, though in each case script was running but I find very little speed improvement in script execution duration.I'm using wait

driver.manage().timeouts().implicitlyWait(10000,TimeUnit.MILLISECONDS);

and along with it

!(driver.findElement(By.xpath("Element Xpath)).isEmpty()) 

or

driver.findElements(By.xpath("Element Xpath)).size()>0

I know I can go for CSS Selectors but in my case that is not feasible due to DOM Tree structure. what can be used instead of

driver.findElements(By.xpath("Element Xpath)).size()>0

this to check if element is present or not and based on that I have to trigger multiple other actions.

回答1:

There are a few issues with your approach.

  1. .implicitlyWait() doesn't actually wait. It sets the timeout for the driver instance so you only need to set it once, not call it each time you want to wait.

  2. driver.findElement(...).isEmpty() won't compile. Maybe you meant .findElements()? Either way, .isEmpty() vs .size() > 0 is going to be a negligible difference in speed.

  3. The main problem is that you have an implicit wait enabled when checking for something to NOT be present... especially a 10s wait. That means that each time an element is checked for, Selenium will wait for 10s even if it's expecting it to NOT be there.

You would be better served by turning off implicit wait (setting it to 0) and then do your existence check for elements you expect not to be there and then turn it back on. That will be 10s x # of existence checks you expect to not be there. Depending on how many existence checks you do, that could add up to a LOT of time. One downside of this, if you have a complex page with background processes, you will need to have a specific wait for the page (or portion of a page) to finish loading before checking for existence of elements with implicit wait off.

Side note... Selenium contributors have stated that implicit waits shouldn't be used period. Use WebDriverWait instead but that's a whole other discussion.



回答2:

There are a handful of approaches to execute your test suite at the optimum speed. Your code block would have given us more insights about the reason of the delay you are experiencing. However with respect to your code snippets here are a couple of remedies:

  • implicitlyWait(10000,TimeUnit.MILLISECONDS);: Day by as more and more Web Applications are adopting to JavaScript, jQuery, AngularJS, ReactJS etc, ExplicitWait i.e. WebDriverWait have become as a mandatory measure to synchronize the fast moving WebDriver instance i.e. the driver with the lagging Browser Client. But again as per the documentation:

Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

  • So the first step would be to get rid of all the implicitlyWait and replace them by WebDriverWait

  • driver.findElements(By.xpath("Element Xpath)).size()>0: findElement() and findElements() are affected by the 'implicit wait' times in force at the time of execution. The findElement(..) invocation will return a matching row, or try again repeatedly until the configured timeout is reached. findElement() should not be used to look for non-present elements, use findElements(By) and assert zero length response instead. All these adds to a lot of overheads. Rather I would recommend a try-catch {} block with a definite Locator Strategy, catch the exception in-case of an error and move ahead.

  • You can find a detailed discussion in NoSuchElementException with isDisplayed() method within try catch block in Selenium
  • As per the current WebDriver-W3C Recommendation the following is the list of preferred Locator Strategies:

  • There is some difference in the performance using CssSelector and XPath. A few take aways:
    • For starters there is no dramatic difference in performance between XPath and CSS.
    • Traversing the DOM in older browsers like IE8 does not work with CSS but is fine with XPath. And XPath can walk up the DOM (e.g. from child to parent), whereas CSS can only traverse down the DOM (e.g. from parent to child). However not being able to traverse the DOM with CSS in older browsers isn't necessarily a bad thing as it is more of an indicator that your page has poor design and could benefit from some helpful markup.
    • An argument in favor of CSS is that they are more readable, brief, and concise while it is a subjective call.
    • Ben Burton mentions you should use CSS because that's how applications are built. This makes the tests easier to write, talk about, and have others help maintain.
    • Adam Goucher says to adopt a more hybrid approach -- focusing first on IDs, then CSS, and leveraging XPath only when you need it (e.g. walking up the DOM) and that XPath will always be more powerful for advanced locators.
    • You can find a detailed discussion in Why should I ever use CSS selectors as opposed to XPath for automated testing?

Conclusion

Keeping the above mentioned factors in consideration you need to:

  • Properly configure Implicit / Explicit Waits and pageLoadTimeout through Selenium
  • Implement the Locator Strategies wisely along with the other approaches discussed above which will help you to get rid of the timeouts.
  • You can find a detailed discussion in Random Selenium E2e Tests Fail because of timeouts on Azure DevOps but work locally and with remote Selenium (BrowserStack Automate)