Saturday, January 16, 2010

Waiting for Windows to Load in Automated GUI Testing

I recently started using Microsoft's UiAutomation framework to do some automated GUI testing. It's slightly better than using Win32 directly (subject of a separate post), but, like all things based in reality, leaves a little something to be desired.

The Ui Automation framework is built around the AutomationElement. The AutomationElement provides methods for finding child windows by their name (or title) and by Automation ID. This is great. With the help of UISpy it's very easy to find any element in an application (even ones with no title).

In the wonderful world of automated GUI testing you often cannot predict how long it will take for a particular UI element to load. Consequently, you are forever writing Thread.Sleep(3000). Not only does this get real old real fast, but it's not very robust since the continuous integration (CI) server running the tests could run significantly slower then your development box.

To solve this problem I wrapped AutomationElement.FindFirst() in a new method FindElementByName() and added some logic to handle the fact that the element may not be immediately available.
/// <summary>
/// Find an element by its Title or Name
/// </summary>
/// <param name="root">
/// The root element to start searching from
/// </param>
/// <param name="name">
/// The Title or Name of the element to search for
/// </param>
/// <param name="retries">
/// The maximum number of times to retry if the element is
/// not found
/// </param>
/// <returns></returns>
public AutomationElement FindElementByName (AutomationElement root,
   string name, uint retries)
{
   Util.ValidateNotEmpty ("name", name);

   Condition c = new PropertyCondition (
   AutomationElement.NameProperty, name,
   PropertyConditionFlags.IgnoreCase);

   if (null == root)
   {
      root = AutomationElement.RootElement;
   }

   // First look for imediate children
   AutomationElement ae = root.FindFirst (
      TreeScope.Element | TreeScope.Children, c);

   if (null == ae)
   {
      ae = root.FindFirst (
         TreeScope.Element | TreeScope.Descendants, c);
   }

   // If we have not found the window by now then it may be slow in
   // opening, so we wait 'time' sec and try again.
   if (null == ae && retries < RETRY_LIMIT)
   {
      retries++;
      uint time = RETRY_FACTOR * retries;

      Log ("  Element \"{0}\" not found, retrying in {1} ms",
         name, time);

      Thread.Sleep ((int)time);

      ae = FindElementByName (root, name, retries);
   }
   return ae;
}

Thursday, January 7, 2010

Validating Arguments

How many times have you seen (or, shame on you, written) this snippet of code to validate that an argument is not null?
public String StopDoingThis(MyRediculousObj foobar)
{
   if (null == foobar)
   {
      throw new ArgumentNullException (
      String.Format ("StopDoingThis: 'foobar' cannot be null",
      GetCallingMethod (), variable_name));
   }

   foreach (Foo foo in foobar.InfiniteFoo())
   {
      Console.WriteLine("Stop it! Please stop it!");
   }

   return "Realy, please stop it!";
}
Why do coders insist on writing this same chunk of code over and over again? I know, it's obvious: "Coders are lazy."

But if we're so lazy why then hasn't every coder from New York to Thailand encapsulated this ever so common validation. I dunno, but here it is. Use it and stop writing this damn validation at the top of every freakin' method!
public String NiceAndClean(FabulousObj sonice)
{
   ValidateNotNull("sonice", sonice)

   return "Look how nice and clean that was :)";
}

public void ValidateNotNull (
   string variable_name, Object parameter)
{
   if (null == parameter)
   {
      throw new ArgumentNullException (
      String.Format ("{0}: '{1}' cannot be null",
      GetCallingMethod (), variable_name));
   }
}

private string GetCallingMethod ()
{
   StackTrace stackTrace = new StackTrace ();

   // We get the second (2) frame.  The first frame would
   // be the method ('Method B') calling GetCallingMethod().
   // What the user really wants in the method that called
   // 'Method B', so we want the second frame.
   return stackTrace.GetFrame (2).GetMethod ().Name;
}
If you're truely a lazy coder then I'd expect you to write a whole bunch of these: ValidateNotEmpty, ValidateBounds, ValidateThisThatAndTheOtherThing. They're quicker than cut and paste, easier to read, and make your code look better than the dude in the cube next to you :p