Enabling UI Testing for Third party WinForms custom controls - 2
In the previous article, I described how we can make the DevExpress Scheduler Control & Appointments visible to Visual Studio UI Testing Framework. In this article, I will describe how we can retrieve rich properties for both these controls. These properties can then be used for validation in Coded UI Test.
In order to achieve this, we need to implement a Property Provider extension for the Visual Studio UI Testing framework.
Step 1:- Implement an Extension Package
An Extension Package is the entry point for any new extension to the Visual Studio UI Testing Framework.The complete implementation of my extension package is given below.
Two points worth calling out.
1. The Assembly attribute which is set for the extension.
2. GetService method - This returns our custom property provider. If other extension points are implemented, we will appropriately modify this method.
[assembly: Microsoft.VisualStudio.TestTools.UITest.Extension.UITestExtensionPackage(
"XtraSchedulerExtensionPackage",
typeof(XtraScheduler.XtraSchedulerExtensionPackage))]
namespace XtraScheduler
{
internal class XtraSchedulerExtensionPackage : UITestExtensionPackage
{
public override object GetService(Type serviceType)
{
if (serviceType == typeof(UITestPropertyProvider))
{
if (propertyProvider == null)
{
propertyProvider = new PropertyProvider();
}
return propertyProvider;
}
return null;
}
public override void Dispose() {}
public override string PackageDescription {get { return "XtraScheduler Extension"; }}
public override string PackageName { get { return "XtraScheduler Extension"; } }
public override string PackageVendor { get { return "Mathew Aniyan"; }}
public override Version PackageVersion { get { return new Version(1, 0); } }
public override Version VSVersion { get { return new Version(10, 0); } }
private UITestPropertyProvider propertyProvider;
}
}
Step 2: Implement the Custom Property Provider
internal class PropertyProvider : UITestPropertyProvider
I have copied this code from Gautam’s Property Provider sample here - https://blogs.msdn.com/b/gautamg/archive/2010/01/05/5-property-provider-of-sample-excel-extension.aspx
I have modified the following methods – GetPropertyNames, GetPropertyDescriptor, GetPropertyValue, GetSpecializedClass, GetPropertyNamesClassType to return values appropriately for Scheduler Control & Appointments.
I modified the IsSupported method as
return (uiTestControl is XtraScheduler) || (uiTestControl is XtraAppointment) ||
(string.Equals(uiTestControl.TechnologyName, "MSAA", StringComparison.OrdinalIgnoreCase) &&
(uiTestControl.ControlType == ControlType.Pane || uiTestControl.ControlType == "Clock"));
Therefore, this property provider will come into effect for controls with MSAA technology & Control Type = Pane & Clock (These values are set in the accessibility implementations).
NOTE: You can only use a subset of UITestControl properties in this method. This method is called during recording, validation & Code generation. During some of these workflows, the live object corresponding to the UI Test Control may not be available and therefore some of the properties will throw exceptions.
The other significant method is GetPropertyValueInternal.
For getting the AppointmentCount from the Scheduler Control, I am returning the Accessible Children Count from Scheduler Control’s accessible object.
For getting the Duration of the Appointment, I am passing the Duration of the appointment in the description field of the Accessibility object.
private object GetPropertyValueInternal(UITestControl uiTestControl, string propertyName)
{
object[] native = uiTestControl.NativeElement as object[];
IAccessible a = native[0] as IAccessible;
if (string.Equals(propertyName, XtraScheduler.PropertyNames.AppointmentCount, StringComparison.OrdinalIgnoreCase))
{
return a.accChildCount;
}
if (string.Equals(propertyName, XtraAppointment.PropertyNames.Duration, StringComparison.OrdinalIgnoreCase))
{
string[] descriptionTokens = a.accDescription.Split(new char[] { ';' });;
return descriptionTokens[1];
}
throw new NotSupportedException();
}
The complete source code for my property provider project is attached.
Caveat: This is a quick & dirty implementation. I have not commented the code nor attempted to use the most appropriate data structures. I recommend you refactor this code if you intend to extend this code for your testing.