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.