Selenium Webdriver.load.strategy unstable - java

I'm having problems loading my page with webdriver. My current (problematic) solution involves using the unstable load with firefox, but I'm open to other solutions.
The Core Problem
The root of all my problems comes from the fact my page will never fully load when I call it normally with webdriver, and thus will never preform the 2nd step, it's just always loading. It loads fine when you just go to the site with a normal browser. I've tried out a few work arounds that work intermittently, including opening the driver to google, and then going to the page which sometimes makes it load, and with
IJavaScriptExecutor js = (IJavaScriptExecutor)Driver;
js.ExecuteScript("return window.stop");
as suggested by this question, which sometimes makes it continue without loading. But neither of those work consistently at all (probably <50% of the time)
The best I've got so far is using the unstable load strategy. However that has its own different problems, all of which only happen sometimes.
1) Sometimes it doesn't wait for the page to load at all, and I get an "Unable to locate element:" exception within milliseconds of loading the page, despite the fact that I have a wait set up:
new WebDriverWait(cdriver, 30).until(ExpectedConditions.visibilityOf(cdriver.findElement(By.id(myId))));
Thread.sleep(3000); solves that problem, but I've read that is a sloppy way to do things.
2) If I get passed that step, my test should click one link, then click another and continue on with the test. However, it often gets stuck after that first click. So if my code is like this:
Thread.sleep(3000);
element1.click();
System.out.println("clicked!");
element2.click();
The first click (which doesn't load a new page, by the way, just a pop up on the same page) will work, but then the system will never print out "clicked!", it's stuck in the same way would be loading the page initially (without the unstable load thing). If/when it makes it over that hurdle, I think the rest of the test is fine.
Any ideas 1) why it works sometimes but not others. 2) how to fix it 3) how to just get my page to load in the first place
Thank you!

Try the following approach:
Don't wait for visibility of element on the page - in your case By.id(myId).
The element can become visible much earlier than the page is fully loaded, before all java scripts are loaded and fired etc.
Wait for some element on the page to be clickeable instead. For example you can wait until link becomes clickeable in this way:
By locatorOfLink1 = By.xpath(....); // By.id, By.name, By.linkText etc.
wait.until(ExpectedConditions.elementToBeClickable(locatorOfLink1));
If the above will not help for problem #2 (the webdriver gets stuck after the click), then send ENTER key to the link instead of the click:
element1.sendKeys(Keys.ENTER);

Related

Java Selenium - Waiting on slow websites

Im testing on a site that sometimes doenst really have a good connection.
Everything works great until it decides to not work properly.
I am seperating every element with a wait.until, everything works normally until the connection gets slow and it believes the element is present and decides to use it.
public static WebElement login_btn(WebDriver driver, WebDriverWait wait) {
wait.until(ExpectedConditions.refreshed(ExpectedConditions.presenceOfElementLocated(By.id("btnEntrar"))));
wait.until(ExpectedConditions.refreshed(ExpectedConditions.elementToBeClickable(By.id("btnEntrar"))));
element = driver.findElement(By.id("btnEntrar"));
return element;
}
I cannot find a way to simulate this until the website becomes terribly slow and I get to see if it works or not. After months of trying I am unable to find out a way to completely wait for the element to be present and not receive a staleElementReferenceException or the site actually going into an error page due to me using an element. Using the site manually without these tests cannot simulate what is happening with the webdriver. Are there any hints or suggests on what I could do?
There are a few good answers you can try in this question and this question. One is to use Chrome dev tools to throttle adjust the download speed, https://stackoverflow.com/a/34728002/2386774. Another is Charles Web Debugging Proxy.
To solve this issue more simply, my suggestion is to specifically wait for the page to load completely then scrape the page. This will allow you to wait once and then you won't have to add waits everywhere. You would need to add additional waits if your page is dynamic, e.g. you click a button and it updates part of the page. In that case, add a wait when the button is clicked and you're good again. No need to add waits everywhere.

Persistent background checking with Selenium

First time poster, long time lurker. I've gotten a lot of great advice to problems from this site, but I haven't found anything here for the topic of this question. Normally I would bug our SME at the office but he's indisposed.
So, we use Selenium Web Driver to do automated tests. I'm working on an application with some mapping and demographics features, so my tests are very function vs. form oriented.
My tests are written such that I have classes/methods that are a part of the puzzle (the site is essentially one workflow where you go from page 1 to page 5 and the same actions need to be performed in steps 2-3, for example, but test A might do something different on page 4 to see the result in page 5. Clear as mud?
Anyways, during manual tests, I can sometimes see an error message pop up on the site (a hidden div that will become visible if it detects an error, but it's usually a very generic/vague error). This error sometimes pops up even if you're able to go through the flow with no other ill-effects. However, I want to capture when these errors happen so I can look for patterns - if this means just logging it to console or failing the test...I can figure that out later.
The immediate problem is having a persistent check in place that will always look for this error during every test. I could create a method and call it in my "action" methods, though this would leave gaps and slow the tests down. Is there any clever way of implementing something like this without slowing the tests down or calling this check every time I do a step in the process? Also, forgive me, I'm still learning Java and the selenium web driver, so if I've said anything stupid, that's why.
Since this message is persistent if it is there, you might try adding a check for it in your test case teardown method. (I would recommend that you reduce the implicit wait time before you do that check, though, otherwise each test will take an extra amount of time waiting for an error message that isn't there.)
Another possible option is to define your own listener on your own test runner and update the testFinished() method to go check for your error message. See this for some ideas.
Since it sounds like the error messages are always in known locations on each page, I would create a method (or methods, depending on how many error message locations there are on a given page) that looks to see if an error exists and then log it before leaving the page. It sounds like you might be using the page object model. If so, you can add these methods to the each relevant page object for easy access.
NOTE: Checking for errors once before you leave the page may not be enough. You may need to check each time you do some action that might cause an error. This is probably not a bad practice anyway because it will help in debugging errors because you will notice an error closer to the time it was triggered, thus narrowing down what caused the error.
If you have the ability, do something like log it as a warning so that it doesn't fail your test but stands out (and is searchable) in your logs.
You seem concerned that checking for all these errors will significantly slow your script. If properly written, it shouldn't add a significant delay. One significant delay you might run into is if you have implicit waits turned on and are checking for elements that don't exist (e.g., unless there's an error). This will cause the implicit wait to be applied each time you search for the missing element and will likely add significant time to the run time. My suggestion is to turn off implicit waits and add explicit waits only where needed. Searching for any element will add some time but 25ms here and there should be negligible in an overall script run.
Have you tried using EventFiringWebDriver?
There is an answer here on what it does:
What is EventFiringWebDriver in selenium?
Newer selenium versions have more types of events present in the interface, which can broaden its use on these types of tests.

Selenium Webdriver with Java: Element not found in the cache - perhaps the page has changed since it was looked up

I am initializing a variable in the beginning of my class:
public WebElement logout;
Later on in the code, in some method, the first time I encounter the logout button, I assign a value to that variable (in the brackets of an if/else statement):
logout = driver.findElement(By.linkText("Logout"));
logout.click();
I then use "logout" once more, successfully, at another stage of my test:
logout.click();
And at the end of the test, at a place where the element is the same (By.linkText ("Logout")), I get this error:
Element not found in the cache - perhaps the page has changed since it was looked up
Why?
EDIT: Actually, I dont successfully use the logout.click(); commant at another stage of my test. Looks like I cant use it again. I have to create a logout1 webelement and use it...
If there has been any changes to the page after you have initially found the element the webdriver reference will now contain a stale reference. As the page has changed, the element will no longer be where webdriver expects it to be.
To solve your issue, try finding the element each time you need to use it - writing a small method that you can call as and when is a good idea.
import org.openqa.selenium.support.ui.WebDriverWait
public void clickAnElementByLinkText(String linkText) {
wait.until(ExpectedConditions.presenceOfElementLocated(By.linkText(linkText)));
driver.findElement(By.linkText(linkText)).click();
}
Then within your code you'd only need to:
clickAnElementByLinkText("Logout");
So each time it will find the element and click on it, as such even if the page changes as it is 'refreshing' the reference to that element it all successfully click it.
The browser rebuilds the DOM structure of the dynamic pages, so the elements do not need to keep you have to find them before to use.
Using XPath, for example. This approach is not correct(can cause exception org.openqa.selenium.StaleElementReferenceException in the future):
WebElement element = driver.findElement(By.xpath("//ul[#class=\"pagination\"]/li[3]/a"));
...// Some Ajax interaction here
element.click(); //<-- Element might not be exists
This approach is correct:
driver.findElement(By.xpath("//ul[#class=\"pagination\"]/li[3]/a")).click();
This is because you are not giving proper time to load the page.So you have to give Thread.sleep(); code for the Given page.
I am also getting the same issue for my project but after using the Thread.sleep(); its working fine for me give the web page as much as it is possible for 30 to 50 secs.

loading java applet on DOM load

I searched for it a lot but probably I am searching wrong strings. A Java applet is feeding live bits into my pages, java applet accesses the input fields on my page and places the information
<input type="hidden" id="F1" value="Nothing Yet">
and then it calls a javascript functionon the page say LivePicker() and then it simply picks up a value
var ClockVal = document.getElementById("F1").value;
document.getElementById("ICSCLOCK").innerHTML = ClockVal;
The problem I am facing is, this works fine but sometimes in firebug console it give errors like LivePicker is not defined, while LivePicker would be working perfectly fine on the page while sometimes it will give F1 is not defined, while my clock would be working fine. All of these errors appear at page load.
Java applet places the data sequentially, it first place the data and then calls the js function to process it. That works perfectly fine on test pages with minimum HTML and JS but when I integrate it to my application, which uses a lot of components from YUI and a lot of my own JS code (which is now minified obviously), it give these errors. One thing I would like to add, before minification, these errors were a lot likely but after minification of JS and CSS, the page load time is reduced to half and the appearence of these errors are reduced to half as well.
I am suspecting this is due to, on page load, applet tries to manipulate the DOM which is not ready yet. Is there anything, which could stop the applet to wait until the DOM is fully loaded? I tried window.onload and onDOMReady function of YUI, they seem to make no effect at all.
Can any one help please?
you could try using setTimeout to delay execution
https://developer.mozilla.org/en/DOM/window.setTimeout
or the jQuery library could also help out with the ready event on the document object
http://docs.jquery.com/Events/ready#fn
The browser should delay executing the window.onload code until after
the DOM tree is created and after all other external resources are fully loaded and the page is displayed in the browser.
The window.onload should work. Your applet must be running before the onload event.
As a test, can you do the following and see if it changes anything:
create a hidden "set" field in the page with value "false";
on window.onload set the value for the "set" field to "true";
in your applet check the "set" field;
only start doing things in your applet if the "set" field is defined and has a value of "true";
One other thing, don't do a busy waiting in your applet to test for the "set" field. Your applet should take no action if the field is undefined or false. You can reactivate it on window.onload if needed.
This problem was resolved using dpb suggestions in slightly different way. This blog post I wrote should explain every bit to those who are facing similar problem.
Controlling Java applet from Javascript especially if you make round-trips to the web page from applet

Hibernate Exception Fixed By Alt+Tab

I've got a very curious problem in Hibernate that I would like some opinions on. In my code if I do the following:
Go to page A
Click a link on page A to be taken to page B
Click on data item on page B
Exception thrown
I get an error telling me:
failed to lazily initialize a collection of role: XYZ, no session or session was closed
Fair enough. But when I do the same thing but add an alt+tab in the middle, everything is fine. E.g.
Go to page A
Click a link on page A to be taken to page B
Hit ALt+Tab to switch to another application
Hit ALt+Tab to switch back to the web browser
Click on data item on page B
Everything is fine.
I'm a little confused as to how switching focus from my application makes it act as I want it to. Does anyone have any light to shine on the subject? I don't think it's a locking issue as even if I do the second set of steps quicker than the first, still no error.
It's a Seam application using Hibernate 3.3.2.GA & 3.4.0.GA.
It's not really related to switching the applications; maybe your browser updates something during focus lost/gained.
The reason for your issue is this:
In the first request, you load an object and store that in the session. This object contains a collection of some kind.
In the next request, you try to do something with the collection but you forgot to call session.refresh(object), first.
What happens is that the session is automatically closed when the first request is finished. But the backed collection in your object still contains a reference to it (so that it can be loaded automatically when you access it for the first time).
are you using javascript? Maybe an event is firing when you switch back to the browser that somehow clears the bad state?
Does your page complete it's rendering? I have found that sometimes when I get errors, instead of displaying the error, the server simply quits producing output. It outputs the error to the log, but thats about it. I end up with a half completed page. View source and see if you get to the end of the body, perhaps your switching caused the server to get lazy, or your browser to terminate the connection prematurely when the error occured
My advice is to do a unit test to see if you can reproduce the error in other environment isolated from the browser ;)

Categories