While automating WPF controls in Coded UI Test, the playback would sometimes through an exception with the following error message:

“Search may have failed at <ControlX> as it may have virtualized children. If the control being searched is descendant of <ControlX> then including it as the parent container may solve the problem.”

 

In this blog, I’ll explain the details behind this playback failure, the current limitation we have in recorder for WPF controls and a workaround to fix this.

 

The control search in playback is essentially a Breadth First Search (BFS) UI tree traversal wherein it looks for the target element within the sub tree rooted under the container element (except for the top level element which is found using a window search directly under the desktop control).  For example, if a search hierarchy generated for a control ‘B’ is

 

TopLevelWindow (TLW)  à A  à B

 

The search steps will be –

 

1.       Window search under desktop for TLW

2.       BFS Search for A under TLW’s subtree.

3.       BFS Search for B under A’s subtree.

 

In WPF, the controls under item container (such as Combo Box, List Box, Tree View, Datagrid) could be virtualized. The virtualized controls have a light-weight Automation peer associated with them which store a minimal set of properties. To fetch all the properties of the element, the element first needs to be “Realized” (i.e. brought into the parent container’s view port). Navigation such as GetParent, GetChildren on the virtualized element is also not possible unless the element is ‘Realized’.

 

Coded UI Test playback mandates that all such virtualized elements and its immediate container needs to be in the search hierarchy. This is because the intermediate search element needs to be ‘Realized’ before the search can proceed further down its sub-tree.

 

[NOTE: The playback does not ‘Realize’ all virtualized elements that comes in the BFS path since ‘Realize’ effectively does a scroll into view of the virtualized element. In order to limit these scrolling side-effects, it only attempts to do a ‘Realize’ of those items which are explicitly defined in the search hierarchy]

 

For example, in the following hierarchy

 

TLW à A à Bà C (Combo Box) à D (virtualized Combo Box Item) à E à F (Target Element),

 

if the search condition does not have C and D in the hierarchy, the playback search will fail. So the ideal search condition in this case should be

 

TLW à C à D à E à F

 

Unfortunately the recorder may not be able to auto-generate this extended level of search hierarchy for all scenarios. For instance, if ‘E’ is at a depth more than 2 from its nearest virtualized item ancestor (‘D’ in this case), the recorder will miss out from including D (and subsequently ‘C’) in the search condition. This is done essentially for performance reasons during recording.

 

The work around for the user is to hand code the extended search hierarchy so that all virtualized items in the ancestor hierarchy are included in the search condition.

 

For example, say the UI tree hierarchy for an element 'L' is

 

TLW à A à B à C (Combo Box) à D (Combo Box Item) à E  à F à G (List Box) à H (List Box Item) à I à J à K  à L (Target Element)

 

D and H can be virtualized. So those need to be included in the search hierarchy. Unfortunately, the recorder will generate the search condition for ‘L’ as,

 

TLW à K à L

 

Note, this is because H and K are separated by more than 2 levels. (Similarly, D and G are separated by more than 2 levels).

 

The search hierarchy needs to be fixed for the playback to succeed. To hand code this –

 

a.       Use the Coded UI Test control locator to go up the UI hierarchy starting from the target element ‘L’.

b.       While traversing up, add H, G, D and C to the UIMap.

c.       In you test code, insert the following lines before accessing UIObject_L.

 

UIObject_K.Container = UIObject_H;

UIObject_G.Container = UIObject_C; // where, UIOjbect_{X} denotes the UIObject generated for control ‘X’ in the UIMap.

 

What we have essentially done over here is stitched the control ‘G’ to its ancestor virtualized control ‘D’ and  control ‘K’ to its ancestor virtualized control ‘H’. Also, note that you need to do this stitching multiple times depending whether there are multiple virtualized items in the hierarchy (in this case there were two, the combo box and the list box).

 

Finally, the exception message mentions something like – “Search may have failed at <ControlX> as it may have virtualized children ... ”. This should be used only as a hint and may not be completely accurate. The error message simply tries to suggest that while searching for the target element, the last virtualized container that the playback BFS came across was <ControlX>. [before the search ultimately failed]. As a small experiment, create a sample WPF application having a button next to a combo box. The UI hierarchy is

 

TLW

|_ ComboBox_A

|_ Button_B

 

Record some action on Button_B.

1.       Modify the uitest file to change the search property of Button_B to something invalid (to make the search fail during playback).

2.       Playback the recorded action [1]

 

You’ll observe a similar exception saying  Search may have failed at ComboBox_A as it may have virtualized children … “ even though the ComboBox_A is actually not in the ancestor UI hierarchy of Button_B.

 

So to summarize:

 

1.       Ensure that the target element has correct properties generated.

2.       Use the hand coding workaround to figure out whether there are virtualized items and if yes, include them in the search hierarchy.