Home > Mobile >  Loop to repeat a method 3 times if condition fails
Loop to repeat a method 3 times if condition fails

Time:10-01

Im looking for a simple way, to repeat a method, when an element(selector) for example a button on a webpage cant be found.

My idea or my plan is, that:

  1. If the selector can be found, the method is done
  2. If the selector cant be found, it should repeat the "FindElement" method up to maximal 3 times
  3. If the selector cant be found after the third try, it should give me an output message of the "NoSuchElementException e"

I tried different loops and i always end up having endless loops like in the code below.

    public static void FindElement(IWebDriver webDriver, string selector)
    {
        int maxTries = 0;

        try
        {
            webDriver.FindElement(By.XPath(selector));
            Console.WriteLine("Element found.");
        }
        catch (NoSuchElementException e)
        {
            if (maxTries !> 3 )
            {
                Console.WriteLine("Element, not found. Retrying.");
                maxTries  ;
                FindElement(webDriver, selector);
            } 
            else 
            {
            Console.WriteLine(e);
            }
        }
    }

CodePudding user response:

What a coincidence: Just a few days ago I wrote a short helper method to separate "retry logic" from "business logic".

private T Retry<T>(Func<T> action, int maxRetryCount, int waitMilliseconds,
                   Func<Exception, bool> retryCondition)
{
    var retryCount = 0;
    while (true)
    {
        try
        {
            // If the action was successful (no exception thrown),
            // we can leave the method.
            return action();
        }
        catch (Exception ex) when (retryCount < maxRetryCount && retryCondition(ex))
        {
            retryCount  = 1;
            Thread.Sleep(waitMilliseconds);
        }
    }
}

Which would be called as follows in your case:

var element = Retry(() => webDriver.FindElement(By.XPath(selector)),
                    2, 0,
                    ex => ex is NoSuchElementException);

Whenever the maximum number of retries is reached, the exception is not caught any more (the when condition fails) and can be caught by your regular exception handling logic instead.

Since you are trying to automate a web browser, you might consider passing something else than 0 as waitMilliseconds, to give the browser time to render the elements that are still missing.

CodePudding user response:

Why don't you put the maxTry outside of your function?

int maxTry=3;
string errorMessage="";
for(int i=0;i<maxTry;i  )
{
    try
    {
         FindElement(webDriver,selector)
         errorMessage="";
         break;
    }
    catch (NoSuchElementException e)
    {
        errorMessage=e;
    }
}
if(errorMessage!="")
{
    Console.WriteLine(e);
}
else
{
    Console.WriteLine("Element found.");
}

CodePudding user response:

For recursion, you should pass the amount of remaining iterations to the function, and decrement it for each iteration.

public static void FindElement(IWebDriver webDriver, string selector, int iterations = 3)
{
    iterations--;

    if (iterations < 0)
    {
        Console.WriteLine("Max iterations passed, exiting")
        return;
    } 

    try
    {
        webDriver.FindElement(By.XPath(selector));
        Console.WriteLine("Element found.");
    }
    catch (NoSuchElementException e)
    {
        Console.WriteLine("Element not found. Retrying.");
        FindElement(webDriver, selector, iterations);
    }
}

CodePudding user response:

You have almost nailed it.

In case of recursive functions like yours the most important part is the exit condition.

In other words how do I determine that it should stop.

  • If the selector can be found, the method is done << return inside try
  • If the selector cant be found after the third try << return inside the if
public static void FindElement(IWebDriver webDriver, string selector, int remainingTries)
{
    try
    {
        webDriver.FindElement(By.XPath(selector));
        Console.WriteLine("Element found.");
        return;
    }
    catch (NoSuchElementException e)
    {
        if (remainingTries == 0)
        { 
           Console.WriteLine(e);
           return;
        }

        Console.WriteLine("Element, not found. Retrying.");
        FindElement(webDriver, selector, remainingTries--);
    }
}
  •  Tags:  
  • c#
  • Related