Selenium is a very useful tool but it can be very, very obtuse.
One challenge is dealing with Ajax; you might click on a button, but without a full page refresh, it's hard to know when to look for expected changes via Ajax and DHTML.
In the past, my test suites had short sleeps, a few hundred milliseconds. This makes them fail sporadically ... every once and a while on my MacBook Pro I'm doing so much other stuff while the tests run that the timing goes screwy.
You're then left with a difficult choice: sleep too short and the tests may fail. Sleep too long and your tests will always be slow.
Fortunately, there's a third option: Selenium's
waitForCondition call. Of course, their documentation is worthless.
In my case, I wanted to wait for a client-side popup <div> to appear:
type("amount", "abc"); type("quantity", "abc"); click(SUBMIT); waitForCondition("document.getElementById('amount:errorpopup')", "5000"); assertText("//div[@id='amount:errorpopup']/span", "You must provide a numeric value for Amount."); assertText("//div[@id='quantity:errorpopup']/span", "Provide quantity as a number.");
I'm making the assumption that once one of two <div> elements appears, they both will. I then use some XPath to get the text inside the <span> inside each <div>, to make sure the correct message was displayed to the user.
But this code doesn't work.
The problem is that
document isn't what you'd expect; I'm guessing that it's some other frame inside the browser (Selenium's UI and code executes in one frame, which runs the actual application inside the second frame).
The solution took some research and the sacrifice of a few small furry animals to obtain:
That works, and it works much faster than adding a Thread.sleep() in the middle of my code.