I find that Selenium tests often fail because page elements are not loaded properly, even if you have set implicit waits. If a test is failing inexplicably at the same point this works for me. Try this (my code is C# but you can do it in other languages):
In test initialisation set up a wait:
globalWait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
Then call the wait when a troublesome page loads:
globalWait.Until(ExpectedConditions.ElementIsVisible(By.Id("myPageElement")));
This forces a wait until the element is visible. It solved a lot of problems for me. Often I set the id to a footer element, or if it is an AJAX page, one of the AJAX retrieved elements. This makes sure that the page has loaded correctly.
Another technique is to write a common routine for login and logoff, and if you are doing a lot of complex tests, logon, do some tests, logoff, then logon and do some more tests. This seems to lead to less spurious errors in Selenium.
My C# login routine:
private void Login()
{
driver.Navigate().GoToUrl(base_url + "/login");
globalWait.Until(ExpectedConditions.ElementIsVisible(By.Id("username")));
driver.FindElement(By.Id("username")).SendKeys(username);
// clear IE password autocomplete
driver.FindElement(By.Id("password")).Clear();
driver.FindElement(By.Id("password")).SendKeys(password);
driver.FindElement(By.Id("btn_login")).Click();
}
My logout routine:
private void LogOut()
{
driver.FindElement(By.Id("lnkMenuLogout")).Click();
}
A test using them:
[TestMethod]
public void EditAccount()
{
Login();
// navigate to account page
driver.FindElement(By.Id("ulMenu")).FindElement(By.Id("lnkMenuAccount")).Click();
Assert.IsTrue(driver.FindElement(By.Id("headName")).Displayed, "Player name not displayed");
string playerChangeName = "Test" + DateTime.Now.ToString("yyyyMMddHHmmss");
driver.FindElement(By.Id("butEditName")).Click();
driver.FindElement(By.Id("surname")).Clear();
driver.FindElement(By.Id("surname")).SendKeys(playerChangeName);
driver.FindElement(By.Id("butSaveName")).Click();
driver.Navigate().Refresh();
// check that edit worked
Assert.IsTrue(driver.FindElement(By.Id("headName")).Displayed, "Player name not displayed after change");
IWebElement element = driver.FindElement(By.Id("headName"));
string playerName = element.Text;
StringAssert.Contains(playerName,playerChangeName,"Player name has not been changed");
LogOut();
}
My final conclusion though is that presently, Selenium is still somewhat 'flakey'. I am currently experimenting with PhantomJS but that appears to be no better. Selenium is the best we have.