4

I want a consistent output when running Selenium WebDriver test cases.

I have more than 30 test cases in a java class. When I run it i'm getting errors in different methods. For eg. Some times it fails in the 12th test case, some times in 8th, some times in 2nd method, Some times all are running without any error. I'm sure all the test cases are correct.

It tests very fast. I thought this would be the problem. So I added

new FireFoxDriver().manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

Even though its not consistent

Can anyone help me asap?

Gnik
  • 7,120
  • 20
  • 79
  • 129
  • 1
    OK, first thing: automated UI integration testing is messy, and unreliable, but it's focus is to help take the load of manual testing. Accept it *now*, UI testing is very very unreliable. The point is to make them *as reliable as possible*. Next thing: this could be for any reason. Tried the ChromeDriver? Have you tried putting in Thread.Sleep? (Or the equivalent of in Java?). Does the page sometimes take a while to load? What kind of selectors are you using? Does it generally fall on XPath selectors? What ones? Are they complex? Have you tried testing it out with simpler selectors? – Arran Oct 03 '12 at 13:44
  • If you provide info about the errors you are getting it might help us answer the question. If the errors are different each time, give examples of each. It sounds like you think the problem might be due to timing. If that's so, also include the code from the test cases that are failing. – Giscard Biamby Oct 03 '12 at 14:50

3 Answers3

11

I'll disagree strongly with Arran's statement that UI testing is very unreliable. It absolutely doesn't have to be. Learning solid approaches to two main issues usually smooths out a lot of problems.

Intermittent failures are most often caused by synchronization issues around dynamic content, or locators which aren't flexible enough to handle changing conditions.

For example, you're extracting a row from a grid/table, and your locators are positional based. (3rd row, 5th cell) The sort order differs on one run, so the test breaks. Some server-side technologies like ASP.NET generate dynamic IDs which can vary, so that's another problem.

I'd encourage you to carefully evaluate your locators/selectors and see if they're robust. Avoid hardwired xpath, use IDs wherever possible--but make sure they aren't dynamic IDs and deal with them appropriately if they are.

You mentioned you've tried using an implicit wait. Make sure you understand the difference between implicit and explicit waits. (Read more here in Selenium docs.) It may be you need explicit waits for the exact conditions for the next steps in your scripts. Do not, repeat NOT use Thread.Sleep or similar manual delays in your tests except in extraordinary circumstances. WebDriver's Wait is a much better approach.

Jim Holmes
  • 1,680
  • 8
  • 10
  • 1
    Thanks, Arran! I'm not saying automation is easy--to the contrary. But I've had good luck in difficult environments getting stable, high-value automation working. – Jim Holmes Oct 04 '12 at 07:02
  • +1 for the XPath comment. Generated XPath makes the worst selectors – Nathan Merrill Aug 21 '13 at 22:10
  • I strongly disagree with your answer.. I am more than 100% sure in cases where test cases randomly fail and pass. "Some server-side technologies like ASP.NET generate dynamic IDs which can vary, so that's another problem." I think we are not talking about this sort of reason why fail. They are unreliable in the sense that the elements are not loaded properly. So we should wait. But how long ??? This is what we mostly encounter when we mean inconsistency. – sajid Jun 25 '18 at 12:08
  • @sajid I'm not sure what you're trying to relay. My point is that UI testing can be stable and high value. Understanding how long to wait is a matter of experience, trial and error, experimentation, and most importantly communication with the developers. – Jim Holmes Jun 27 '18 at 05:40
  • @JimHolmes Thank you for the answer. I used many of your suggestions, excluding thread.sleep, but the driver still clicks the element I want it clicked intermittently. I am using simple locators like Ids and wait for the webdriver to locate the element before being clicked. But in vain. Are there any other solutions to explore. Perhaps a different testing package? – analytical_prat Mar 31 '21 at 22:59
2

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.

GrahamJ
  • 528
  • 4
  • 15
1

My best answer for you is to add "reliability and recovery code".

For instance, maybe your tests are trying to click something, but randomly the webelement is stale for whatever reason. So add code that catches StaleElementExceptions and retries a max of 5 times before failing for real.

Or, maybe sometimes the page loads a little too slowly and the content hasn't been updated before Selenium thinks its done (AJAX functionality). This causes the check to fail but when looking at a screen shot, the page is actually correct because this all happens in less than .2 seconds. So, add a selenium wait which waits for the content to be updated before using the assert call.

This essentially gives you more reliable results since your test code now knows how to handle common situations with the selenium framework.

Hope this helps!

Jason Smiley
  • 289
  • 4
  • 12