Problems accessing UI when not started as application

Feb 11, 2010 at 1:50 PM
Edited Feb 15, 2010 at 8:58 AM

Hi forum,

I have big problems testing my WinForm (NET 3.5). First of all, I have due to explizit demand NO application to be able to be launched. Currently I generate my UI to be tested from within my test. That sounds strange, but this is what we need this for our purposes.

So my tests starts like this:

private void ShowFormFromThread()
{
SetupMainForm();
_MainForm.ShowDialog();
}

 
public void TestMenuItems()
{
Thread showMainFormAsDialogFromThread = new Thread( new ThreadStart( ShowFormFromThread ) );
showMainFormAsDialogFromThread.Start();
}
 


So my Form is visible in a correct way. I started it from a thread to be able to show it with ShowDialog(). Else my testapp would hang. No I want to get the window-object, but no approach worked for me. Desktop.Instance.Windows and the direct way run always in a timeout.

So I tried this:

    private AutomationElement GetMainWindow()
    {
      AutomationElement aeDesktop = AutomationElement.RootElement;
      AutomationElement aeMainForm = null;

      int numWaits = 0;
      do
      {
        aeMainForm = aeDesktop.FindFirst( TreeScope.Children, new PropertyCondition( AutomationElement.NameProperty, MYNAME ) );
        numWaits++;
        Thread.Sleep( 200 );
      } while( aeMainForm == null && numWaits < 50 );

      if( aeMainForm == null )
      {
        throw new Exception( "Can't find form" );
      }

      return aeMainForm;
    }

 

This gives me an AutomationElement. No I started to get the MenuBar and the MenuItems. This isnt working, my Spy-Tools (UISpy and Visual UI Automation Verify) are also freezing when I want to access my window.

When I start my window from it's real application (I tried this just for testing, this is no option unfortunately), then it works fine.

My window is instaciated properly and the menu items are working as expected, when I click them manually. But I can't automate a thing.

My problems are mostly based on the strange approach of starting our window-under-test from within the test itself, but can anybody give me some advice how to workaround this issue without beeing forced to start an application?

Thank you very much,

Grimwulf

Feb 11, 2010 at 4:19 PM

So just to get it right: White runs on the same process as your application/window? Why is this a demand? Can you launch a "LauncherApplication" for your white-tests? Then the Window is launched the same way as now but you have an application you can launch that runs in its own process and works well with white. Let me tell you my insights when running the tests on the same process that white attaches to (and it is important that it is the same PROCESS, if just the thread is different it makes no real difference).

I had similar issues because i wanted to be able to mock some services before starting my application that i then attached white to. So my basic start procedure looked like this:

MockServicesThatAreConsumedByApplication -> StartApplicationInTestProcessButInOtherThread -> RunTestsWithWhite

This gave me some issues:

* once the first TestMethod terminated i wasn't able to start another test because there can always only be one ApplicationObject per AppDomain (even if the old Application instance should have been destroyed/is NULL). This might not be the case for you because you start your window by calling ShowDialog (sorry i am a WPF developer and don't know much about WinForms). This can be solved by starting another AppDomain where you open your window/run your application.

* if calling Application.Kill() on the white-ApplicationObject you kill your testrunner process (when using TestDriven.Net this is "ProcessInvocation.exe")

* when debugging, the app freezes when hitting a breakpoiint because white always calls window.WaitWhileBusy when waiting for a action to complete what means that Process.WaitForInputIdle is called. In your case the testProcess/debugProcess is the same as the process white waits for to become InputIdle. My guess is that hitting a breakpoint kind of polls if you are doing a new step and never lets your process get InputIdle (at least the symptoms look like that). As a consequence your BusyTimeOut runs out and the test fails.

I was only able to resolve this issues by starting a "TestingRemoteProcess", using IPC with a NamedPipe to send some "configuration data" to the "TestingRemoteProcess" that configured my mocks and started the application i wanted to test with white. Then i attached white to the TestingRemoteProcess and fetched my window. After closing the window i ask my TEstingRemoteProcess if all Mocks could be verified and shut down the IPC/TestingRemoteProcess. That works well until now.

I am not shure if this is a answer to your problem, if your problem lies shomewhere else please post more information so i can understand the problem.

kind regards,

kidrocker

Feb 17, 2010 at 12:06 PM

Hi kidrocker,

 

You got it right, and a workaround for our problem could be to use some kind of a launcher which creates our form to test outside the current process. The reason for our need lies in the need to mock some functionality. We will use a separate launcher app in future :-) This should work for us.

Thank you very much for your answer and for your suggestions.

Kind regards,

Grimwulf