Selenium WebDriver if conditions consuming lot of time - java

Lately I have written the following code to click on any of the following elements which is visible:
Purpose : It is basically a never ending loop to repeat the same action again i.e, click 3 buttons.
Problem : When I run the code it seems to take arbitrary time between 1 second- 7 seconds to click a button, tough page gets loaded successfully in an instant. Hence I am eager to know what is it in the code which the delaying the operation? and Is there any efficient way to reduce the time?
battle(WebDriver driver1)
{
try { if(driver1.findElements(By.xpath("....")).size()!= 0)
{
driver1.findElement(By.xpath("....")).click();
}
if(driver1.findElements(By.xpath("....")).size()!= 0)
{
driver1.findElement(By.xpath("....")).click();
}
if(driver1.findElements(By.xpath("....")).size()!= 0)
{
driver1.findElement(By.xpath("....")).click();
}
battle(driver1);
}
catch(Exception e)
{
battle(driver1);
}
}

here you are using xpath to click on button. generally xpath will take more time compare to ID and CSS. Please give try by taking ID and CSS and then u can check the difference in execution time. You can refer to this link to understand why xpath takes more time for execution.

If I were to guess, you probably have an implicit wait set. Any time you look for an element that doesn't exist, Selenium will wait for the implicit time (5s or whatever is set) until the timeout is reached and then move on. My suggestion is to remove the implicit wait completely and see how it goes. If you need a wait, add in a WebDriverWait for each scenario.
Another, maybe minor issue, is that for each element to be clicked you are scraping the page twice... once to see if it exists and then again to click the element. You can alter your code to only scrape the page once, store the results in a variable, check to see if the collection is empty, and click the element if it's non-empty.
Since you are repeating code 3 times, I would write a function that handles that code and then call it as needed.
There are some other things that I've changed. One example is that you seem to want to always run battle no matter what. Rather than recursively calling battle and calling battle after an exception, just add a while loop that never ends. Having said that, once you polish this code up and use it somewhere you will likely want to add an escape... some way for the user to exit the program and your while would depend on that flag being set but that's another discussion.
battle(WebDriver driver1)
{
while (true)
{
clickIfExists(By.xpath("xpath1"));
clickIfExists(By.xpath("xpath2"));
clickIfExists(By.xpath("xpath3"));
}
}
public void clickIfExists(By locator)
{
List<WebElement> e = driver1.findElements(locator);
if (e.size() > 0)
{
e.get(0).click();
}
}

Related

Selenium : Element is found when using Thread.sleep(), but not Implicit/Explicit waits

I read about how beneficial in using Implicit/Explicit waits, and decided to abandon Thread.sleep() in my code. However, the result is opposite. Using Thread.sleep(), I can actually locate the element, while Implicit/Explicit waits result in the ElementClickInterceptedException: element click intercepted: [duplicate] error for the same element.
The element I am trying to simulate a click on is an "I AGREE" button located in a dialog box. The following is the DOM for the button which I am trying to click.
And the following is the code to simulate the click.
Using Implicit Wait
driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
Result : ElementClickInterceptedException: element click intercepted: [duplicate] error
Using Explicit Wait
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement I_Agree;
I_Agree = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[1]/div/div/div[4]/a")));
I_Agree.click();
Result : ElementClickInterceptedException: element click intercepted: [duplicate] error
Using Thread.sleep()
Thread.sleep(20000);
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
Result : Element is found and click can be executed.
Hope to have advice on any mistakes I may have done.
implicitlyWait waits for the element existence.
So in case of
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
Selenium will try clicking that element immediately after the goal element appears.
In many cases the element can still be not clickable so utilizing the implicitlyWait may often cause exceptions.
Using ExpectedConditions.visibilityOfElementLocated will mostly work better, but still there are several situations this will not work.
In some cases the goal element can be out of the visible screen. In this case you will have to scroll to the goal element in order to bring it into the visible screen and then click it properly.
In some other cases during the page rendering Selenium will indicate element as visible and clickable while actually some other element may be overlapping on the goal element so clicking on it will cause the wrong element accepting the click. However if you give some more wait the page rendering process will complete and now you can click the goal element properly.
This is seems to be your case.
In most cases the overlapping element will be some kind of spinner element.
If so you should add the ExpectedConditions.invisibilityOfElementLocated condition to wait until the spinner / other overlapping element is disappeared.
To give more precise answer we need to see the specific site you are working on and the actual test flow you are doing.
You can see more about the ElementClickInterceptedException here, here, here and at more resources.
UPD
From your comments I see you did not actually understand. Both implicitly and explicitly waits are pooling the DOM to find element matching the passed condition. In both cases at the moment the condition is met Selenium will immediately stop waiting and polling, it will return an element (or Boolean true in some cases) and continue to the next command.
Implicitly wait is waiting for element presence. So in many cases the element itself is still not finally rendered and may still not be clickable or visible but it is already present, so in your case
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a"))
may return the element that is still not ready to be clicked on.
This is why it is preferred to use explicit waits like ExpectedConditions.visibilityOfElementLocated since in this case Selenium will wait polling the DOM until it finds the desired element to be visible, this is much more mature state of the element on the page and it can normally be clicked on this point.
However, sometimes it can be some spinner etc. on that element. This is some external problem. So in this case we need to add ExpectedConditions.invisibilityOfElementLocated to wait until that spinner is disappeared.
There are more cases explicit wait will not be enough to be applied on the element itself. Sometimes you will have to scroll the desired element into the view, sometimes you will even need to use JavaScript click etc.

How to create wait in selenium that waits for a web element to finish refreshing

I'm fairly new to Selenium and I'm writing a test for a web app using it. In doing this, I'm using assertions to make sure the web app is working correctly. For a few of these assertions, I'm asserting on a web element that has a numeric value in which the expected number is known. The problem is when a change is made that changes this numeric value the change happens gradually based on how fast the internet connection is. Up to this point have resorted to using sleep's to wait for the element to finish refreshing before I use assertions but I would like to make it so this wait is no longer than the time it takes for the element to stop refreshing and thus not have to include sleep's that are either too short or too long.
You should try this:
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(<specific locator of element>));
Sleep is not a good option because you wait always expected the amount of time.
In the approach presented above you always wait for the visibility of a specific element. When an element is visible your test steps will go forward. There is no extra wait time which you got with implicit sleep
Avoid using sleep and replace it with an implicit wait or use expected condition if applicable. below is c# code for it
int time =10; // set maximum time required for operation
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(time));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath(""))); //replace "" with your desired xpath
The above code will wait for max 10 seconds for an element to be visible. but if it appears earlier then it will jump to next process so you need not have to wait for a specific time. Also, there are other expected conditions available like ElementExists, ElementToBeClickable etc. I will leave it to you to explore the appropriate option for yourself
if you wan t to use implicit wait specifically use below code
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(50));

Selenium - wait for page to render dynamic page

I have a Dynamic web page that refreshes and loads new data. I am using Selenium and I need to wait till the page has finished rendering before I can continue checking the page. I have seen many posts about waiting for the page to load or using explicit waits (implicit wait could solve the problem but is very unelegant and not fast enough). The problem with using explicit waits is not having any info on what will come up after the refresh. I have seen some solutions talking about waiting for all the connections to the server to end but that will not promise me that the actual UI has finished rendering.
What I need is a way to know if a page has finished to render (not load!!)
First of all you DO KNOW what sctructure will come after the page will load. You don't know what tags were not on the page, but you know what DOM will look like. That's why usually it's worst practice to test with page text, but a good one to have a website tested by DOM only. So, depending on what structure appears on the page you will need to have explicit ways waiting for specific tags will appear on the page.
One more solution (but as I told it's not really the best practice) is to wait for document.readystate is "complete". This state will not help in every situation, but if you have something still loading on the page, in more then half cases it will not return complete. So, you should have some kind of implicit state that is executing:
string readyState = javascript.ExecuteScript("if (document.readyState) return document.readyState;").ToString();
and then checking:
readyState.ToLower() == "complete";
btw if you will use protractor as an angular js application test executor, it's waiting for angular page loaded by default, or in some difficult situations you can use:
browser.waitForAngular();
OR do something in a callback
button.click().then(function() {
// go next step
});
I have had similar problem with the product I am testing. I had to create special functions for click,click_checkbox,sendKeys and getText for example. These include try catch methods for cathcing NoSuchElement StaleElementReference exceptions. Also it retries if the actions fail, like sending the wrong text.
document.readyState
This isnt enough for you. It only waits for the DOM to load. WHen the HTML tag are loaded, it returns "complete". So you have to wait for each individual item.
This works for me well with dynamically rendered websites - I do not have a time constraint in getting the data as it would run in background for me, if efficiency is an issue may be this is not the solution for you (50s is a huge time for any website to load after the ready state is completed) :
Wait for complete page to load
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
Make another implicit wait with a dummy condition which would always fail
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true
}
catch (TimeoutException te) {
}
Finally, instead of getting the html source - which would in most of one page applications would give you a different result , pull the outerhtml of the first html tag
String script = "return document.getElementsByTagName(\"html\")[0].outerHTML;";
content = ((JavascriptExecutor) driver).executeScript(script).toString();

Unable to predict the pop up apperaence

I'm facing a issue regarding a popup(not a browser popup an application one), and im handling it perfectly. But the problem is i dont know when it appears and by default i'm using Thread.sleep for 20 seconds in order to handle it. Now i have to cut down the time and have to handle the issue effectively.Can any one pls help me out without using Thread.sleep.
Thread.sleep(20000);
if(oASelFW.driver.findElement(By.xpath("//div[#class='fsrFloatingMid']")).isDisplayed()){
oASelFW.driver.findElement(By.xpath("//a[#class='fsrCloseBtn']")).click();
}
You need to make use of Explicit waits which will allow to wait until certain condition is satisfied - which in your case is until is element present.
WebElement whatever = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//div[#class='fsrFloatingMid']"));

Webelement.click in selenium

I am using selenium to do the UI automation for a web application.
1) My doubt is
when i use the click() method like, right_btn.click() whether it just clicks the right_btn and comes out or it just waits for the underlying actions to be completed before it moves out???
bcoz i read this
When i googled for WebElement.click() http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/WebElement.html it says like, it gets blocked whenever the click() involves opening a new page but here it doesnt opens a new page rather it involves in service call.
2) What i actually want to know?
I want to know this actually to calculate the latency involved in carrying out each actions in the UI. Is there any way to calculate the latency for each UI actions, just like we can see the latency time when we use inspect element in chrome. Thanks in advance.
In java, you can make a Date a = new date() object with the current time, just before your right_btn.click() and then wait for the resulting page to open, (if in a new tab/window - switch to it) and then find some element on that page
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("someid")));
After that returns the element, make another Date b = new Date()
The latency is the difference in milliseconds int millis = b-a;
Yes, a small part of that total time is Selenium searching for the 2nd element, but I'm afraid this might be the best you can do with java/selenium for your purpose.
I am not too sure if I understood your question exactly
How to calculate Latency is hard , but for intercepting calls you can use browserMobProxy in your code and check if particular call is complete and move on

Categories