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.

Write “Hello, World” extension

  1. Create a new C# Class Library project with name UITestHelloWorldPackage.
  2. Add reference to following two Coded UI Test assemblies using the “.NET” tab in the “Add Reference” dialog –
    • Microsoft.VisualStudio.TestTools.UITest.Common.dll
    • Microsoft.VisualStudio.TestTools.UITest.Extension.dll
  3. Rename the file Class1.cs (class Class1) to HelloWorldPackage.cs (class HelloWorldPackage).
  4. Open HelloWorldPackage.cs, delete the existing code and add the code given below –
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 & Deploy the extension

Build and deploy the binaries to "%CommonProgramFiles%\Microsoft Shared\VSTT\10.0\UITestExtensionPackages" directory. To deploy, you use following commands –

  • md "%CommonProgramFiles%\Microsoft Shared\VSTT\10.0\UITestExtensionPackages"
  • For 32 bit - xcopy /y "%~dp0\bin\Debug\UITestHelloWorldPackage.*" "%CommonProgramFiles%\Microsoft Shared\VSTT\10.0\UITestExtensionPackages\*.*"
  • For 64 bit - xcopy /y "%~dp0\bin\Debug\UITestHelloWorldPackage.*" "%CommonProgramFiles(x86)%\Microsoft Shared\VSTT\10.0\UITestExtensionPackages\*.*"

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 –

  • Create “HKLM\Software\Microsoft\VisualStudio\10.0\TeamTest\UITest\UITestExtensionPackages” key.
  • Under this, create a key with your extension name like “HelloWorldPackage” here. Set the default value of this key to full path of the extension. For example, “C:\MyDir\MyExtension.dll”.

Verify the extension

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 -

  1. Using the steps mentioned in this blog, enable logging for Coded UI Test.
  2. Launch new VS and create a new Coded UI Test.
  3. Record some steps and generate code. Close the Coded UI Test Builder.
  4. Go to "%temp%\UITestLogs\CodedUITestBuilder\LastRun" directory and view UITestLog.html. Among other entries, you will see “Hello, World” string here too.  The below picture shows the output.  Note - There could be multiple “Hello, World” string because the extension is called once for each extension point.

image

Understanding the extension code

Now that we have verified that the extension is working properly, let us understand the code by breaking into sections.

Adding UITestExtensionPackageAttribute assembly attribute
[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.

Implementing 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.

The GetService() method
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.

The Dispose() method
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.

Other properties of the class
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

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.