Wednesday, March 10, 2010

Automated Retries

I'm still working on building up an automated GUI testing framework. It turns out that many GUI interaction are not very reliable for a number of reasons (the time it takes a for a dialog to pop-up can vary from session to session, for example).

To solve this my framework will retry some operations until successful or some limit is reached. Of course I don't want to write the same retry logic over and over again, so I came up with this little library function that makes use of lambdas to keep it generic.

public class AutomatedRetry
{
    public uint RETRY_FACTOR = 50;

    public bool Try (Func<bool> action, uint limit)
    {
        for (uint tries = 0; tries < limit; tries++)
        {
            if (action ())
                return true;
            else
            {
                uint time = tries * RETRY_FACTOR;
                Log ("  retry in {0} ms", time);

                Thread.Sleep ((int)time);
            }
        }

        return false;
    }

    ...
}

The function Try() takes a delegate that returns true when successful and false otherwise. It will keep calling action until it returns true or the limit is reached.

Here is an example of it being used:

public AutomationElement FindElementByName (
    AutomationElement root, string name)
{
    AutomationElement elm = null;

    Func<bool> action = () =>
    {
        elm = FindElementByName_ (root, name);

        return null != elm;
    };

    AutomatedRetry trier = new AutomatedRetry ();
    trier.Try (action, RETRY_LIMIT);

    return elm;
}

I make a delegate (action) that calls the method that is going to get retried and tests the result to see if it was successful or not. In this case we are trying to find a UI Element by it's name. FindElementByName_() will return the element if successful or null if not. To use the AutomatedRetry we simple call Try() with the action delegate and the number of times to retry. Pretty cool, huh?

No comments:

Post a Comment