Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

White is very slow to get elements in window #146

Closed
guitardude89 opened this issue Aug 13, 2013 · 16 comments
Closed

White is very slow to get elements in window #146

guitardude89 opened this issue Aug 13, 2013 · 16 comments

Comments

@guitardude89
Copy link

Hello,
Any help or pointers would be very helpful. I'm automating an engineering application, and am trying to push a few buttons on it with a view to speeding up some workflow.
White finds the main window in a fraction of a second - but any child members take forever (28 seconds).
Here's the code I'm using:

        TestStack.White.Configuration.CoreAppXmlConfiguration.Instance.RawElementBasedSearch = true;

        Process[] localByName = Process.GetProcessesByName("SACSExecutive");
        int i = localByName.Length;
        while (i > 0)
        {
            i -= 1;
        }
        i = localByName.Length;
        int procid = localByName[i - 1].Id;
        TestStack.White.Application application = TestStack.White.Application.Attach(procid);
        Window window = application.GetWindow("SACS 5.5 V8i",InitializeOption.NoCache.AndIdentifiedBy("SACS 5.5 V8i"));

        IUIItem[] f = window.GetMultiple(TestStack.White.UIItems.Finders.SearchCriteria.All);

        System.Windows.Automation.AutomationElement tab = window.GetElement(TestStack.White.UIItems.Finders.SearchCriteria.ByText("Multi Run Generator"));

I've also tried this way, and the results are pretty much exactly the same:

        Button btnOpenMulti = window.Get<Button>("Open Multirun File");
        Button btnRunMulti = window.Get<Button>("Run Multi Analyses");
        btnOpenMulti.Click();

Any way to speed this up??? They're always in a constant section of the screen, but exact pixel location will of course vary with the display.

Thanks

@JakeGinnivan
Copy link
Member

Why are you using RawElementBasedSearch? That is likely the source of your issues.

From: guitardude89 [mailto:notifications@github.com]
Sent: Tuesday, 13 August 2013 16:54 PM
To: TestStack/White
Subject: [White] White is very slow to get elements in window (#146)

Hello,
Any help or pointers would be very helpful. I'm automating an engineering application, and am trying to push a few buttons on it with a view to speeding up some workflow.
White finds the main window in a fraction of a second - but any child members take forever (28 seconds).
Here's the core I'm using:
TestStack.White.Configuration.CoreAppXmlConfiguration.Instance.RawElementBasedSearch = true;

    Process[] localByName = Process.GetProcessesByName("SACSExecutive");

    int i = localByName.Length;

    while (i > 0)

    {

        i -= 1;

    }

    i = localByName.Length;

    int procid = localByName[i - 1].Id;

    TestStack.White.Application application = TestStack.White.Application.Attach(procid);

    Window window = application.GetWindow("SACS 5.5 V8i",InitializeOption.NoCache.AndIdentifiedBy("SACS 5.5 V8i"));



    IUIItem[] f = window.GetMultiple(TestStack.White.UIItems.Finders.SearchCriteria.All);



    System.Windows.Automation.AutomationElement tab = window.GetElement(TestStack.White.UIItems.Finders.SearchCriteria.ByText("Multi Run Generator"));

I've also tried this way, and the results are pretty much exactly the same:
Button btnOpenMulti = window.Get("Open Multirun File");
Button btnRunMulti = window.Get("Run Multi Analyses");
btnOpenMulti.Click();

Any way to speed this up??? They're always in a constant section of the screen, but exact pixel location will of course vary with the display.

Thanks


Reply to this email directly or view it on GitHubhttps://github.com//issues/146.

@guitardude89
Copy link
Author

Hi,

Thanks for your response. I tried both with and without RawElementBasedSearch, and the time it takes is very similar - between 26 and 28 seconds.

Any other ideas?

Thanks

@JakeGinnivan
Copy link
Member

Does your application have a lot of elements? Does UIA Verify or Inspect have the same performance problems when exploring the application?

From: guitardude89 [mailto:notifications@github.com]
Sent: Wednesday, 14 August 2013 13:57 PM
To: TestStack/White
Cc: Jake Ginnivan
Subject: Re: [White] White is very slow to get elements in window (#146)

Hi,

Thanks for your response. I tried both with and without RawElementBasedSearch, and the time it takes is very similar - between 26 and 28 seconds.

Any other ideas?

Thanks


Reply to this email directly or view it on GitHubhttps://github.com//issues/146#issuecomment-22633307.

@guitardude89
Copy link
Author

It does have quite a few elements, quite a few panes with tabs and toolbars which have buttons on them and a few checkboxes. I've been using WinSpy++ and UISpy, nether have the performance issues, the elements are populated within a second or so. Neither does the System.Windows.Automation library directly (although I've tried to stay away from it since its a tad ugly). I'm en route to work at the moment but I'll send the Windows Automation code which I'm now trying instead (which doesn't exhibit the slow performance). Maybe I'm doing something wrong code-wise in White (I'm not a trained programmer).

@guitardude89
Copy link
Author

This is what appears to work with System.Windows.Automation:

        Process[] localByName = Process.GetProcessesByName("SACSExecutive");
        int i = localByName.Length;
        while (i > 0)
        {
            i -= 1;
        }
        i = localByName.Length;
        int procid = localByName[i - 1].Id;
        var mainWindow = AutomationElement.RootElement.FindChildByProcessId(procid);
        AutomationElement Tab = null;
        AutomationElementCollection allChildren = mainWindow.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Tab));
        foreach (AutomationElement automationElement in allChildren)
        {
            Console.WriteLine(automationElement.Current.Name);
            if (automationElement.Current.Name == "Multi Run Generator")
            {
                Tab = automationElement;
            }
        }
        //if Multi Run Generator TAB is not selected in SACS, the below line will fail since "Tab" AutomationElement is null.  Therefore we need to try/catch it
        if (Tab == null)
        {
            System.Windows.MessageBox.Show("In the SACS Executive, make sure that the \"Multi Run Generator\" tab is selected.  Then click OK in this Message Box and the program will continue.");
            foreach (AutomationElement automationElement in allChildren)
            {
                Console.WriteLine(automationElement.Current.Name);
                if (automationElement.Current.Name == "Multi Run Generator")
                {
                    Tab = automationElement;
                }
            }
        }
        AutomationElementCollection Toolbars = Tab.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar));
        AutomationElementCollection Buttons = Toolbars[0].FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
        AutomationElement OpenButton = null, RunButton = null, ClearButton = null;
        foreach (AutomationElement Button in Buttons)
        {
            if (Button.Current.Name == "Open Multirun File")
            {
                OpenButton = Button;
            }
            if (Button.Current.Name == "Run Multi Analyses")
            {
                RunButton = Button;
            }
            if (Button.Current.Name == "Remove All Runfiles From List")
            {
                ClearButton = Button;
            }
        }
        Mouse.Click(procid, (int)(ClearButton.Current.BoundingRectangle.BottomLeft.X + ClearButton.Current.BoundingRectangle.BottomRight.X) / 2, (int)(ClearButton.Current.BoundingRectangle.TopLeft.Y + ClearButton.Current.BoundingRectangle.TopRight.Y) / 2);
        Keyboard.Enter(procid);
        Mouse.Click(procid, (int)(OpenButton.Current.BoundingRectangle.BottomLeft.X + OpenButton.Current.BoundingRectangle.BottomRight.X) / 2, (int)(OpenButton.Current.BoundingRectangle.TopLeft.Y + OpenButton.Current.BoundingRectangle.TopRight.Y) / 2);
        Keyboard.Type(procid, rootDirectory + "\\multidyn.runx");
        Keyboard.Enter(procid);
        Mouse.Click(procid, (int)(RunButton.Current.BoundingRectangle.BottomLeft.X + RunButton.Current.BoundingRectangle.BottomRight.X) / 2, (int)(RunButton.Current.BoundingRectangle.TopLeft.Y + RunButton.Current.BoundingRectangle.TopRight.Y) / 2);

@JakeGinnivan
Copy link
Member

In the code above, why do you have IUIItem[] f = window.GetMultiple(TestStack.White.UIItems.Finders.SearchCriteria.All);? That could take ages to run.

Also try removing the .AndIdentifiedBy() on initialization options.

Finally, you can turn on more verbose logging with

CoreAppXmlConfiguration.Instance.LoggerFactory = new WhiteDefaultLoggerFactory(LoggerLevel.Debug);

@guitardude89
Copy link
Author

Regarding:

IUIItem[] f = window.GetMultiple(TestStack.White.UIItems.Finders.SearchCriteria.All);

This was a piece of test code that I ran just to see what would happen if I stored all elements in an array. I've just removed it and:

System.Windows.Automation.AutomationElement tab = window.GetElement(TestStack.White.UIItems.Finders.SearchCriteria.ByText("Multi Run Generator"));, takes pretty much just as long to run as collecting all the elements in the 'f' array.

I've also removed the .AndIdentifiedBy() option, and it still took 28 seconds to go through each line.

@JakeGinnivan
Copy link
Member

What is logged when your code runs? Use CoreAppXmlConfiguration.Instance.LoggerFactory = new WhiteDefaultLoggerFactory(LoggerLevel.Debug); to get debug level logging

@guitardude89
Copy link
Author

A lot of stuff shows up in the console. Is it saved to a file anywhere?

@JakeGinnivan
Copy link
Member

No, but we use Castle's logging abstractions, so you can use another LoggerFactory to do whatever you want

@JakeGinnivan
Copy link
Member

This should be fixed in the next (v0.12) release. Please reopen this if it still is slow.

@keremispirli
Copy link

did you try to use Get() instead of GetElement() ? I see that you tried it with buttons, but what about tabs?

window.Get<Tab>(TestStack.White.UIItems.Finders.SearchCriteria.ByText("Multi Run Generator"));

I expect it to prevent string comparison of ALL the controls and compare strings of only Tab elements, since type criteria is always inserted as first criteria. [ see SearchCriteria.AndControlType() ]

OTOH there was indeed an issue about clicking controls which waits at least as long as "BusyTimeout" configuration before click, so decreasing that to 1000 can be a quick fix in that case. I hope it is among what Jake is referring as "should be fixed in 0.12" =)

@JakeGinnivan
Copy link
Member

Yeah, the issue was that the Silverlight busy cursor had the same number as a normal cursor. Hopefully that fixes these slowdowns, they don't seem to affect everyone.

@keremispirli
Copy link

Thanks for quick answer! The wait-before-click issue i mentioned was in WPF though, not Silverlight. Does it affect it too?
And is that committed in latest code, if I download and build it myself? Or should I wait for release and jump in if it's not fixed?

@JakeGinnivan
Copy link
Member

You can grab the latest builds off the build server or build yourself. Build server is at http://teamcity.ginnivan.net, you can login as guest.

The issue I mentioned affects WPF, it's normal cursor matched a silverlight busy cursor, so white was waiting internally.

@keremispirli
Copy link

ok, that makes sense. will do, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants