Finding elements is slow!

Mar 10, 2009 at 8:10 PM
I'm trying to use White for acceptance testing a medium-size .NET application. The application opens in about twenty seconds. A test that clicks "File" and then clicks "Exit" takes slightly more than two minutes to run.

Most of the time, if I want to find something, it is pretty near the top of the subtree I am working with. Finding the AutomationElement that I am looking for using a TreeWalker is fast -- it takes perhaps two seconds to go through all the AutomationElements from the current one to a depth of three controls.

And there's no caching of siblings, so if I need to find two menu items, it's going to take four minutes.

Anyway, I made everything fast with the following code:

private DictionaryMappedItemFactory _factory = new DictionaryMappedItemFactory();

private AutomationElement Find(AutomationElement element, string name, int maxDepth)
{
    if (maxDepth == 0)
    {
        return null;
    }
    TreeWalker walker = TreeWalker.RawViewWalker;
    AutomationElement current = walker.GetFirstChild(element);
    while (current != null)
    {
        if ((string) current.GetCurrentPropertyValue(AutomationElement.NameProperty) == name)
        {
            return current;
        }
        current = walker.GetNextSibling(current);
    }
    current = walker.GetFirstChild(element);
    while (current != null)
    {
        AutomationElement found = Find(current, name, maxDepth - 1);
        if (found != null)
        {
            return found;
        }
        current = walker.GetNextSibling(current);
    }
    return null;
}

private UIItem Find(UIItem item, string name, int maxDepth)
{
    AutomationElement element = Find(item.AutomationElement, name, maxDepth);
    if (element == null) return null;
    return (UIItem) _factory.Create(element, item.ActionListener);
}

private T Find<T>(UIItem item, string name) where T : UIItem
{
    return (T)Find(item, name, 4);
}



By the way, why is it so hard to paste code here? This place is called CodePlex, fer the love of potatoes!
Coordinator
Mar 11, 2009 at 4:30 AM
Can you provide the source code of the test?
Mar 11, 2009 at 12:36 PM
For the slow version, it takes long enough that I assumed the tests were failing and the methods were never going to return and that White or UIA was irrevocably broken and unusable. I spent about a full day trying to track down the problem. So, if you don't provide a faster version, please at least warn people that a large application might take a couple minutes to find a particular UI item.

// setup:
ProcessStartInfo info = new ProcessStartInfo(PATH);
info.Arguments = ARGUMENTS;
_application = Application.Launch(info);
// wait for application to start...
Thread.Sleep(20 * 1000);
_window = _application.GetWindow(MAINWINDOWNAME);

// test, slow version:
Debug.WriteLine(DateTime.Now); // 8:28:53 AM
Menu file = _window.MenuBar.MenuItem("File");
Debug.WriteLine(DateTime.Now); // 8:30:44 AM
Menu exit = file.SubMenu("E&xit") ?? file.SubMenu("Exit");
file.Click();
exit.Click();
Thread.Sleep(2000);
Assert.That(_application.HasExited, Is.True);

// test, fast version:
Debug.WriteLine(DateTime.Now); // 8:34:10 AM
Menu file = Find.ByName<Menu>(_window, "File");
Debug.WriteLine(DateTime.Now); // 8:34:14 AM
Menu exit = file.SubMenu("E&xit") ?? file.SubMenu("Exit");
file.Click();
exit.Click();
Thread.Sleep(2000);
Assert.That(_application.HasExited, Is.True);

May 18, 2009 at 11:15 PM
Edited May 18, 2009 at 11:24 PM

Any follow up with this issue? I'm noticing unacceptable slowness as mentioned in the this thread, as well. Unfortunately I cannot use the above solution because I'm not using .NET 3.5 and don't have access to TreeWalker and AutomationElement. I'd really like to see a way to make my test cases faster since White is a valuable tool.

Thanks!

May 19, 2009 at 12:27 PM

You should be able to use UIAutomation with .NET 2.0 -- it doesn't require any C#3.5-isms. I believe it was introduced it C#3.0, which has no language changes. You'll probably have to copy over the relevant DLL to some accessible location other than the .NET3 GAC.

Coordinator
May 25, 2009 at 10:57 AM

I am  not sure whether you have tried this.

http://white.codeplex.com/Wiki/View.aspx?title=Speed%20up%20performance%20by%20Position%20based%20search

Jun 27, 2009 at 3:51 PM

Is there a method to find a control in White which doesn't recurse?  Using FindFirst with TreeScope.Children I can find a TextBox in 40ms; searching using p.Get<TextBox>("aTextBox") (where p is a Panel) takes 50s!  It seems searching through a Panel with NumericUpDown controls takes an especially long time.  I had hoped I could use p.Items to get the controls contained in the Panel but it seems it recurses too.  I can't use position based search because my application has lots of controls which are hidden in a scrolling Panel and it seems the locations don't get saved.

Coordinator
Jun 29, 2009 at 3:02 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Dec 15, 2009 at 10:58 PM

I want to confirm that the work-around described in this thread worked here.