This is the second post in this series on the extensibility of Coded UI Test. If you have not read the first post on the Introduction to Coded UI Test Extensibility, please do so now to understand this post better. In this blog, we will walk-through the steps to create a “Hello, World” extension for Coded UI Test.
using System; using System.Diagnostics; using Microsoft.VisualStudio.TestTools.UITest.Common; using Microsoft.VisualStudio.TestTools.UITest.Extension; // Attribute to denote that this assembly has UITest extensions. [assembly: UITestExtensionPackageAttribute("HelloWorldPackage", typeof(UITestHelloWorldPackage.HelloWorldPackage))] namespace UITestHelloWorldPackage { internal class HelloWorldPackage : UITestExtensionPackage { public override object GetService(Type serviceType) { Trace.WriteLine("Hello, World"); return null; } public override void Dispose() { } public override string PackageDescription { get { return "Sample Extension for Coded UI Test"; } } public override string PackageName { get { return "Hello World Extension"; } } public override string PackageVendor { get { return "Sample by Microsoft Corporation"; } } public override Version PackageVersion { get { return new Version(1, 0); } } public override Version VSVersion { get { return new Version(10, 0); } } } }
Build and deploy the binaries to "%CommonProgramFiles%\Microsoft Shared\VSTT\10.0\UITestExtensionPackages" directory. To deploy, you use following commands –
Note – The above assumes you are building Debug build which is default in VS. Also, if you are using Windows Vista or higher, you will need to do above steps from CMD window with administrative privilege to access "%CommonProgramFiles%".
For deploying, another alternative if for some reason the author does not want to copy to the predefined directory is to add following in registry –
At this point, you have created your first Coded UI Test extension that writes “Hello, World” in the trace file. We will take a look at the code more closely in a while but before that let us verify that the extension is getting loaded and working as expected. To do so, follow the steps below -
Now that we have verified that the extension is working properly, let us understand the code by breaking into sections.
[assembly: UITestExtensionPackageAttribute("HelloWorldPackage", typeof(UITestHelloWorldPackage.HelloWorldPackage))]
The UITestExtensionPackageAttribute assembly level attribute informs the Coded UI Test tool that this assembly contains one or more extensions. The assembly attributes are metadata that can be read quickly without fully loading the assembly and this helps the tool in performance. Here the first parameter to the attribute is just any string identifier and the second parameter is the type that implements the UITestExtensionPackage class.
internal classHelloWorldPackage : UITestExtensionPackage
All Coded UI Test extensions need to have an entry point as a class deriving from the UITestExtensionPackage class. Once the tool identifies an assembly as an extension using the attribute mentioned above, it creates the class implementing the UITestExtensionPackage abstract class and calls GetService() method on it to get the actual extension points.
public override object GetService(Type serviceType)
The GetService() method returns the appropriate service or the extension point as asked. For example, if this package is implementing UITechnologyManager extension point, then when GetService() is called with typeof(UITechnologyManager), it should return the instance of class that implements this service or extension point. In the above example, we are not implementing any of the extension points and hence we are always returning null.
public override void Dispose()
The Dispose() method, like elsewhere in .NET, is used to do any resource cleanup. For more info, refer MSDN on IDisposable.
public override string PackageDescription public override string PackageName public override string PackageVendor public override Version PackageVersion public override Version VSVersion
These properties are used in identifying the extension and provided information on the same to the user in case of error etc.
Debugging the extension is like debugging any other class library project – attach to the appropriate process and set breakpoints. The process during playback is QTAgent32.exe and during recording\assertion\code generation is CodedUITestBuilder.exe. Note that you have to launch the builder and then attach to it. Alternatively, you can use this trick to always attach to CodedUITestBuilder.exe as soon as it is launched or use Debugger.Break() API to break at appropriate point. Many a times, debugging extension issue for recording\playback scenario on the same machine could be tricky because while debugging you are changing machine states (like active window) which recording and playback are sensitive to. In such cases, Remote Debugging is better option.
The complete code for this walk-through is attached as UITestHelloWorldPackage.zip.
From “Hello, World”, move on to a more complete sample in the next blog.