Search code examples
wpfui-automationcaliburn.microwhite-framework

WPF UI Automation with Caliburn.Micro?


I am attempting to write some UI automation tests for a WPF application that is using Caliburn.Micro and White. I am using CM's builtin conventions to bind my controls to the view model's properties and methods. I am also using Conductor classes so that I may have multiple views visible on a single screen. This generally means that multiple controls on a screen can end up having the same x:Name value. It will just get bound to a different view model. A good idea of what I am trying to do can be seen in the HelloScreens sample application that comes with CM.

The problem that I am running in to is that I will have multiple XAML elements with the same x:Name attribute so that CM can handle all of the binding work for me. This unfortunately means that multiple UIItem objects will have the same UI Automation ID. The only way I have found to get, for instance, different TextBlock elements with x:Name="DisplayName" is to make a call such as the following:

SearchCriteria criteria = SearchCriteria.ByAutomationId("DisplayName").AndIndex(1);
WPFLabel label = myWindow.Get<WPFLabel>(criteria);

This means my tests need to know the exact order that different controls are placed on the screen, which seems very brittle. I can see my tests all breaking just by adding another view model.

  • Is there a way to specify the Automation ID other than using the x:Name attribute?
  • Would this be easier if I used the UI Automation framework directly instead of using White?
  • Or, do I really have to forego CM's convention based binding and give everyting unique x:Name values and bind them by hand?

UPDATED

To clarify what I mean by having multiple views visible at once, here is my general layout. I have my ShellViewModel which I derive from Conductor<IScreen>.Collection.OneActive. Then my view has an ItemsControl that is bound to the shell view model's Items property. Each item template shows a button that is meant to load that specific IScreen into a ContentControl that is on the shell's view. So, If I try to look for an element with x:Name="DisplayName", I have the label on the shell view, the label on the button in the ItemsControl as well as a label inside of the ContentControl.


Solution

  • Whilst the AutomationId by default comes from the x:Name attribute, you can override it by setting AutomationProperties.AutomationId.