How To: Make playback wait for certain event?


One of the FAQs on Coded UI Test is how to make playback wait for certain event? For example, how to wait for the window to show up or how to wait for the progress bar to disappear etc.


The answer is to use appropriate UITestControl.WaitForControlXXX() method from the list below –


Note – This capability was not available in VS 2010 Beta 2 but was added after that.



  1. WaitForControlReady() – This waits for the control to be ready to accept mouse/keyboard input.  The engine implicitly calls this API for all actions to wait for the control to be ready before doing any operation. However, in certain esoteric scenario, you may have to do explicit call.

  2. WaitForControlEnabled() – This waits for the control to be enabled.  For example, you can use this wait till the “Next” button of the wizard is enabled (where the wizard is doing some asynchronous validation of the input by making calls to the server). 

  3. WaitForControlExist() – This waits for the control to exist on the UI.  For example, you are expecting an error dialog after the application has done the validation of the parameters. The time taken for validation is variable. You can use this method here to wait for the error dialog.

  4. WaitForControlNotExist() – This waits till the control cease to exist on the UI.  For example, you can use this for progress dialog to go away.

  5. WaitForControlPropertyEqual(string propertyName, object propertyValue) – This waits for the specified property of the control to have the given value.   For example, you can use this to wait for the status text to change to Done.

  6. WaitForControlPropertyNotEqual(string propertyName, object propertyValue) –  This waits for the specified property of the control to not have the given value.   For example, you can use this for edit box to be not read-only i.e. editable.

  7. WaitForControlCondition(Predicate<UITestControl> conditionEvaluator) – This waits till the specified predicate returns true.  This can be used for complex wait operation (like OR conditions) on a given control.  For example, you can use this to wait till the status text is “Succeeded” or “Failed”.  The code for this example would look like –



    Code Snippet



    1. // Define the method to evaluate the condition

    2. private static bool IsStatusDone(UITestControl control)

    3. {

    4.     WinText statusText = control as WinText;

    5.     return statusText.DisplayText == “Succeeded” || statusText.DisplayText == “Failed”;

    6. }


    7. // In test method, wait till the method evaluates to true

    8. statusText.WaitForControlCondition(IsStatusDone);


  8. static WaitForCondition<T>(T conditionContext, Predicate<T> conditionEvaluator) – While all the above are instance method of UITestControl, this one is static method. This also waits till the specified predicate returns true but it can be used for complex wait operation (like OR conditions) on multiple controls.  For example, you can use this to wait till the status text is “Succeeded” or an error dialog pops up.  The code for this example would look like –



    Code Snippet



    1. // Define the method to evaluate the condition

    2. private static bool IsStatusDoneOrError(UITestControl[] controls)

    3. {

    4.     WinText statusText = controls[0] as WinText;

    5.     WinWindow errorDialog = controls[1] as WinWindow;

    6.     return statusText.DisplayText == “Succeeded” || errorDialog.Exists;

    7. }


    8. // In test method, wait till the method evaluates to true

    9. UITestControl.WaitForCondition<UITestControl[]>(new UITestControl[] { statusText, errorDialog }, IsStatusDoneOrError);

All these methods have following behaviour –



  • The methods return true if the wait is successful and false if the wait failed.

  • The implicit timeout for the wait operation is specified by PlaybackSettings.WaitForReadyTimeout property.  The default value of this property is 60000 i.e. one minute as the unit is milliseconds.

  • The methods have an overload to take explicit timeout in milliseconds.  Caveat: When the wait operation results in an implicit search for the control or, when the application is busy, the actual wait time could be more than the timeout specified.

The above functions are powerful and flexible and should satisfy almost all condition. In case these does not (and I would be interested to know about that) and you need to hard wait\sleep in your code, the recommendation would be use Playback.Wait() API instead of Thread.Sleep() API.  The reasons for this are –



  1. There is PlaybackSettings.ThinkTimeMultiplier using which you can modify you sleep.  By default this variable is 1 but you can increase\decrease it to change the wait time all over the code.  For example, if you are specifically testing over slow network (some other slow performance case), you can change this variable at one place (or even in the configuration file) to 1.5 to add 50% extra wait at all places.

  2. Playback.Wait() internally calls Thread.Sleep() (after above computation) in smaller chunks in a for-loop while checking for user cancel\break operation.  In other words, Wait() lets you cancel playback before the end of the wait whereas sleep might not or throw exception.

Comments (17)

  1. subbu says:

    hello Gautam, yet another great blog, keep it up

    i have question here , i got a scenario in my app; where as a user i upload list  of employees to AUT, and AUT takes variable time period to process may be 2 minutes to 20,30 .. minutes , i want to continue my test after a button available in my web form

    so i want to try out '3.WaitForControlExist() ' but you have mentioned the default value of this property is 60000 i.e minute  PlaybackSettings.WaitForReadyTimeout

    does it mean that WaitForControlExist() will end-up raising Timeout exception ?

    thanks

    subbu

  2. The WaitForControlExist() has an overload that can take a timeout too.  In both cases, WaitForControlExist() will return bool and not throw TimeoutException.

  3. kp says:

    I am new to VS2010 premium. I need to calculate response time for getting a document back from the site. We dont have load or perfoimance tests in premium. SO i need to do this with code ui .What is the best way.Could you explain me in detail

  4. @kp – sorry for the late reply.  Coded UI Test is not meant for the above scenario.  You should use Load Test.

    Thanks.

  5. gtest says:

    Howdy,

    Which of the wait controls can be used to wait for manual input tho be entered and verified?

    Or, should I put a wait  control on an object after the test field and proceed after confirmation?

    Can you point me to code samples of either of these ?

    Cheers,

  6. @gtest – There is no direct support of manual intervention in the control in this release.  The manual operation that you want to perform would probably be changing the state of certain control – so you can wait on that state and use the time while it is waiting to perform the action.

    Thanks.

  7. Hello Gautam, first of all yours is a pretty good blog and a great source of info. Ok so we are testing a Sharepoint app and have successfully used WaitForControlReady, WaitForControlEnabled and WaitForControlExist in the controls we use; there is however one that keeps failing; after we click on a Sharepoint site's "Sign in" link, this opens a list of links (visually this really seems like a menu with menu items but they're all links), we need to click on the "Sign in as a different user" link (visualized as a menu item) and we are able to do so for the first say 4 attempts, but then after a while we are unable to do so even if we use WaitForControlReady on this link before clicking on it. Do you know if connections to controls somehow expire? do you know how to overcome this problem? I remember having to do some sort of refresh on some controls while using winrunner back in 2002 so I was wondering if you have ever experienced this issue.

    Thanks in advance.

  8. Hi Joe,

    Thanks for the encouragement.

    From your description, it seems like Sharepoint is changing the actual UI control underneath.  My suggestion would be to try doing explicit Find() call on the test control everytime before the operation.  This will force find the control and rebind it with actual UI control underneath.

    Thanks.

  9. Thanks just like you've said, for some reason the properties for this control were being changed after the 4th iteration on the script, navigating to different URL's seemed to affect it.

    -Joe

  10. Madhu says:

    Gautam,

    I have around 200+ coded UI test cases in which a few Coded UI test cases time out while checking for some controls. The controls are available on the screen and responding, but the framework doesn't recognize them or does not throw a Control Not found exception, instead keeps looking for it until the test case times out. I have shared the trace at social.msdn.microsoft.com/…/008a9a0c-86bc-4de6-8f68-d55361a2522c Can you please help me.

  11. @madhu – Forum is the right place for this. I will ping someone from the team to check on this thread.

  12. Andy says:

    Guatam

    Thanks for the above, i was wondering if you could give an example of the waitforControlReady being parametrised i have a search bar that could bring back multiple records i want to search on a record wait for it to be populated by the search then use codedUi to click on it?

  13. @Andy – I am not sure I follow you completely.  Your case seems bit complex – can you put a post on forums so that someone could help you.  Refer blogs.msdn.com/…/forums-are-the-best-place-to-ask-questions.aspx

  14. Satya says:

    Gautam, I am facing a strange behavior with WaitForControlExist(). I have a very simple scenario where I will run an exe which launches a window. I am checking whether this Window launched or not using WaitForControlExist. After that I am closing this window and relaunching. But this time, if I try to get the value of WaitForControlExist() it is returning false. I found a similar issue in forums at social.msdn.microsoft.com/…/e142e840-f65f-4d15-8819-ab05caab24d2

    but could not get the solution.

    The only work around I could apply is have two objects for UIMap.  and use each at 1st and 2nd validation.

    Have you heard/come across of this issue anytime/? what could be wrong in this case?

  15. @Satya – This sounds like a bug. Can you try making a dummy change to the search property of the control – i.e. make a change and then rollback that change.  This will force the search.

  16. Chris Moore says:

    Gautam,  Thanks for the example code snippets!   I hope you don't mind a small suggestion.  It would be great if you could add the examples to the reference documentation pages for the wait methods themselves.  I find the MSDN reference pages most helpful when they have examples of usage.    

  17. @Chris – Thanks for the suggestion.  Our User Education team is already working on this following your suggestion.