Automatically update test plan with build number

A great feature in Microsoft Test Manager is that it allows you to track which application build your are running your tests against. This is useful for manual testing to track which tests was run against a particular build, it will be assigned to a bug reported during testing and it is used to locate test assemblies used for running automated tests.

It’s really simple to set this up, just go to the properties for the test plan and assign the build definition to the test plan:

image

Unfortunately you need to assign the Build in use manually, which is both tedious and easy to forget.

The solution to this is of course automation. The TFS 2013 build templates can easily be extended to run a post build script (typically PowerShell). See http://msdn.microsoft.com/en-us/library/vstudio/dn376353.aspx if you want to know more about how to run a script in the build process.

The script below will find all test plans in the team project where the build definition is used and update them with the latest build. All you need to do is add the script to source control and reference it in the build definition:

image

Running the build will update the test plans using the build definition to the latest build:

image

The latest version of the script is available from TFS Community Build Extensions on Github here: ApplyVersionToAssemblies.ps1. A snapshot is shown below:

##———————————————————————–

## <copyright file=”UpdateTestPlanBuildNumber.ps1″>(c) http://TfsBuildExtensions.codeplex.com/. This source is subject to the Microsoft Permissive License. See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. All other rights reserved.</copyright>

##———————————————————————–

# Update all test plan using the current build definition with the latest build number.

#

  

# Enable -Verbose option

[CmdletBinding()]

  

# Disable parameter

# Convenience option so you can debug this script or disable it in

# your build definition without having to remove it from

# the ‘Post-build script path’ build process parameter.

param([switch]$Disable)

if ($PSBoundParameters.ContainsKey(‘Disable’))

{

   Write-Verbose “Script disabled; no actions will be taken on the files.”

}

  

# If this script is not running on a build server, remind user to

# set environment variables so that this script can be debugged

if(-not $Env:TF_BUILD -and -not ($Env:TF_BUILD_BUILDURI -and $Env:TF_BUILD_BUILDDEFINITIONNAME -and $Env:TF_BUILD_COLLECTIONURI))

{

   Write-Error “You must set the following environment variables”

   Write-Error “to test this script interactively.”

   Write-Error ‘$Env:TF_BUILD_BUILDURI – For example, enter something like:’

   Write-Error ‘$Env:TF_BUILD_BUILDURI = “vstfs:///Build/Build/15″‘

   Write-Error ‘$Env:TF_BUILD_BUILDDEFINITIONNAME – For example, enter something like:’

   Write-Error ‘$Env:TF_BUILD_BUILDDEFINITIONNAME = “MyProduct.Main.CI”‘

   Write-Error ‘$Env:TF_BUILD_COLLECTIONURI – For example, enter something like:’

   Write-Error ‘$Env:TF_BUILD_COLLECTIONURI = “http://localhost:8080/tfs/DefaultCollection”‘

   exit 1

}

  

# Make sure build uri is set

if (-not $Env:TF_BUILD_BUILDURI)

{

   Write-Error (“TF_BUILD_BUILDURI environment variable is missing.”)

   exit 1

}

Write-Verbose “TF_BUILD_BUILDURI: $Env:TF_BUILD_BUILDURI

 

# Make sure build definition name is set

if (-not $Env:TF_BUILD_BUILDURI)

{

   Write-Error (“TF_BUILD_BUILDDEFINITIONNAME environment variable is missing.”)

   exit 1

}

Write-Verbose “TF_BUILD_BUILDDEFINITIONNAME: $Env:TF_BUILD_BUILDDEFINITIONNAME

 

# Make sure tfs collection uri is set

if (-not $Env:TF_BUILD_COLLECTIONURI)

{

   Write-Error (“TF_BUILD_COLLECTIONURI environment variable is missing.”)

   exit 1

}

Write-Verbose “TF_BUILD_BUILDDEFINITIONNAME: $Env:TF_BUILD_BUILDDEFINITIONNAME

 

[Reflection.Assembly]::LoadWithPartialName(‘Microsoft.TeamFoundation.Client’)

[Reflection.Assembly]::LoadWithPartialName(‘Microsoft.TeamFoundation.TestManagement.Client’)

[Reflection.Assembly]::LoadWithPartialName(‘Microsoft.TeamFoundation.Build.Client’)

 

# Find all test plans using this build definition

$tpc = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($env:TF_BUILD_COLLECTIONURI)

$tcm = $tpc.GetService([Microsoft.TeamFoundation.TestManagement.Client.ITestManagementService])

$buildServer = $tpc.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer])

$teamProject = $buildServer.GetBuild($Env:TF_BUILD_BUILDURI);

$testProject = $tcm.GetTeamProject($teamProject.TeamProject);

$testPlans = $testProject.TestPlans.Query(“SELECT * FROM TestPlan”)

 

$matchingTestPlans = @()

foreach($testPlan in $testPlans)

{

    if($testPlan.BuildFilter.BuildDefinition -eq $Env:TF_BUILD_BUILDDEFINITIONNAME)

    {

        $matchingTestPlans += $testPlan

    }

}

 

# Update test plans with latest build

if($matchingTestPlans)

{

   Write-Host “Will update test plans using $Env:TF_BUILD_BUILDDEFINITIONNAME to $Env:TF_BUILD_BUILDURI to $($matchingTestPlans.count) test plans.”

  

   foreach ($matchingTestPlan in $matchingTestPlans) {

     if(-not $Disable)

     {

        $matchingTestPlan.BuildUri = $Env:TF_BUILD_BUILDURI

        $matchingTestPlan.Save()

        Write-Verbose $matchingTestPlan.Name – version applied”

     }

   }

}

else

{

   Write-Warning “Found no test plans to update.”

}

 

Extending TFS Work Item using a web page and the WebpageControl Revisited

Update 140831: This article has been refreshed with new images and content.

Have you ever wanted to add custom behavior to the TFS work item tracking system? TFS is very flexible when it comes to adding fields, rules and state transitions. But when we need more specialized behavior there is usually only one solution – to implement custom work item controls. It’s pretty straight-forward to implement a work item control (http://witcustomcontrols.codeplex.com/ has some good examples), but we need to implement the control for each client we want to use it (Visual Studio, Web access) and also the control must be deployed to each machine where the client is run.

A much simpler approach can be to implement the extension as a web page and host the web page in the work item form. This solution works with any client (since it’s just a web page) so you won’t have to have one implement for each client type. In TFS 2010 the WebpageControl was introduced, which can be used to host a custom web page inside a work item form. We can configure the control to pass data from the work item to the web page when the control is displayed. So with the WebpageControl we can use the TFS API to write a web page that can surface more or less any data in the work item UI.

In this example I will extend the Test Case work item type with a tab that shows the test suites where the test case is used together with the status of the latest test run in each of the suites.

Note: it’s recommended to work with TFS customization in a sandbox environment so you don’t disturb production use of your TFS. A very easy way to get a development environment for TFS is to use Brian Keller’s Visual Studio / TFS 2012 virtual machine.

The WebpageControl isn’t that much documented on MSDN so I’m going take you through the steps of extending a work item type with the control and linking it to a custom web page.

1. Implement the web page for the extension you want. Since this is just a web application it’s simple to develop, debug and test the extension. Design the page so data can be passed from the work item to the page using URL parameters (http://localhost:9000/test/results?teamprojectName=Scrum2013&testCaseId=313 in this case).

image

2. Add a WebpageControl to the work item type. The easiest way to add a control is to use the Process Template Editor (part of the TFS Power Tools):

image

Make sure to set the Dock property to Fill if you want the control to use the whole tab space.

3. Configure the WebpageControl using the Control Settings:
Set the URL to display and other properties as appropriate:

image

Note the use of field names. You can reference any field with it’s unique reference id, for instance the Team Project name would be $(System.TeamProject).

4. Save and update the work item type definition. Refresh the client you are using to make sure the test case type definition has been updated.

5. Open a test case and see the new control with the custom web page content appear under the Test Suites tab.

image

Simple, wasn’t it? Feel free to leave comments on what you think of this approach.

Next up I will walk you through the code for the Test Results page.

TechDays 2014 (SWE) – Från kod till produktion på 60 minuter

I höst är det dags för nästa TechDays i Sverige, denna gång 18-20 november på Kistamässan i Stockholm.

Själv har jag förmånen att hålla ett pass om releasehantering som specifikt kommer att handla om hur man med hjälp av senaste versionen av Visual Studio kan sätta upp en releaseprocess på ett väldigt smidigt sätt. Vi kommer gå igenom hela flödet från kod till release och även få med stödjande tekniker som automatiserad testning och miljöhantering.

Info om sessionen hittar du här: http://www.techdays.se/Program/Sessioner/Fran-kod-till-produktion-pa-60-minuter-eller-hur-du-med-hjalp-av-Release-Management-for-Visual-Studio-kan-implementera-en-automatiserad-releaseprocess

Har du idéer på saker du skulle vilja se mer av inom release management så skriv en kommentar.

image

Implementing a password field in a TFS build definition

Here’s another TFS build related thing I’ve been asked on and off and still cannot find a sample on the web to refer to.

The scenario in this case is pretty obvious; we want a field in a TFS build definition to hold sensitive information that shows a character mask instead of the text value in clear text, i.e. the Password field in the image below:

image

Click on the […] button and a custom dialog is shown where we type in the password:

image

In this example I’ve chosen an approach where the build template is extended with a custom argument type representing the sensitive value and displays a custom formatted string instead of the underlying value. The value is edited using a custom editor in the build definition. This is a technique that’s been around since TFS 2010 and Jason Pricket has written a post on the basics of creating a custom editor (http://blogs.msdn.com/b/jpricket/archive/2010/01/18/tfs-2010-custom-process-parameters-part-3-custom-editors.aspx) a long time ago.

You need to create a custom TFS build activity to hold the code for the extension. If you want to learn how to create a TFS build activity see http://msdn.microsoft.com/en-us/library/hh850441.aspx for an example. The custom activity in this example is in the Solidify.RM.Build.Activity namespace.

First add a class in the custom activity to hold the password field. Mark the class Serializable and I also use field attributes to provide a display name and set the RefreshProperties to All (this will make the grid in the build definition refresh when the underlying value changes).

The real logic in this extension is to override the ToString method that renders the value as stars instead of the sensitive string. Here’s the code for the password field:

[Serializable]

public class PasswordField

{

   [DisplayName("Password"), RefreshProperties
    (System.ComponentModel.
RefreshProperties.All)]

   public string Value { get; set; }

 

   public override string ToString()

   {

      if (this.Value != null)

      {

         return new string(‘*’, this.Value.Length);

      }

      return string.Empty;

   }

}

Next add a WinForm dialog to the activity that will be used to capture the password, something like this will do fine:

image

Here’s the simple code for the dialog:

public partial class PasswordDialog : Form

{

   public PasswordDialog(string password)

   {

      InitializeComponent();

      passwordTextBox.Text = password;

   }

 

   public string Password

   {

      get

      {

         return passwordTextBox.Text;

      }

 

      set

      {

         passwordTextBox.Text = value;

      }

   }

 

   private void okButton_Click(object sender, EventArgs e)

   {

      this.DialogResult = DialogResult.OK;

      this.Close();

   }

 

   private void cancelButton_Click(object sender, EventArgs e)

   {

      this.DialogResult = DialogResult.Cancel;

      this.Close();

   }

}

Then to connect the dialog to the build process parameter we need a custom UITypeEditor to display the dialog. The code for the UITypeEditor is more or less boilerplate code in this case, it takes a PasswordField argument as an obect parameter and initializes the PasswordDialog with that value. The we pick up the result and assign it back to the process parameter.

public class PasswordEditor : UITypeEditor
{
   public override object EditValue(ITypeDescriptorContext 
          context,
IServiceProvider provider, object value)
  
{
      if (provider != null)
     
{
         var editorService = (IWindowsFormsEditorService)
         provider.GetService(
typeof(IWindowsFormsEditorService));
         if (editorService != null)
        
{
           
var password = value as PasswordField;
           
using (var dialog = new PasswordDialog
                                    (password.Value))
           
{
               dialog.Password = password.Value;
              
if (editorService.ShowDialog(dialog) ==
                   DialogResult.OK)
              
{
                  password.Value = dialog.Password;
              
}
           
}
        
}
      }
      return value;
   }

   public override UITypeEditorEditStyle GetEditStyle
                   (
ITypeDescriptorContext context)

   {
     
return UITypeEditorEditStyle.Modal;
   } 
}

That’s the custom activity part. Next we need to customize a build definition to use the password type. First add a new argument to the build process of type Solidify.RM.Build.Activity.PasswordField. I also initialize the argument with a new object of the same type to make sure it’s always defined:

image

Then configure the metadata for the password argument, this is where we bind the argument to the custom editor. The important detail here is to provide the password editor using the full name of the type and assembly (Solidify.RM.Build.Activity.PasswordEditor,Solidify.RM.Build.Activity):

image

Finally use the password field as desired in the build template, save, check in the customized template into TFS and you’re ready to go.

How to add an enum to a TFS build definition

Recently I was asked how you go about to create an enum/drow-down argument in a TFS build definition. It’s actually a quite easy thing to solve and requires very little code. But it does require a fair bit of plumbing and since I didn’t find an example on how to do this I’m posting the steps here.

This is the scenario: I want a drop-down argument in my build definition that’s bound to an enum value, i.e. let me select the build status from a known set of values:

image

First add an enum to a TFS build activity:

image

I’m assuming you’re familiar with the process of TFS build extensibility. If you need an example of how to create a TFS build activity see http://msdn.microsoft.com/en-us/library/hh850441.aspx for an example.

Next add an argument of the BuildStatusEnum type to your build definition:

image

To get the enum to show as drop-down you need to add metadata to render it correctly. Open the metadata editor in from the Metadata argument and add the BuildStatus argument as a parameter. Then specify Microsoft.TeamFoundation.Build.Controls.EnumPropertyEditor, Microsoft.TeamFoundation.Build.Controls as the Editor, this does the trick of rendering the enum as a drop-down in the build definition process later on. The EnumPropertyEditor is one of the built-in editors which is convenient to use instead of implementing this logic yourself. If you’re curious of what other editors there are then take a look at this post http://bartwullems.blogspot.se/2012/07/tfs-build-using-built-in-editors.html and dig deeper by using a .NET reflection tool to investigate the code.

image

That’s all you need to do to setup the design time experience, now you can go on and use the enum in the build definition as you intend to.

image

WitCustomControls for 2013 Update 2 released

We’ve added a 1.2.2.0 release at https://witcustomcontrols.codeplex.com/ to fix an issue caused by changes in the jscript structure in TFS 2013 Update 2.

Release Notes

This release contains the following changes:

Download the latest release here: https://witcustomcontrols.codeplex.com/releases/view/123638.

Presentation från “Har du en DevOps i ditt team?” (SWE)

Tack alla som kom, bra diskussioner om ett i mitt tycke viktigt ämne!

Nu finns presentation från seminariet uppe på SlideShare: http://www.slideshare.net/Solidify-Sverige/solidify-dev-ops

Nästa gång kör vi i Göteborg (den 12 september). Passa på att boka dig om du vill komma och lära dig mer om DevOps rollen och hur Visual Studio 2013 ALM hjälper dig bli mer effektiv i teamet. Info och registrering på http://informator.se/seminarier/seminarier/har-du-en-devops-i-ditt-team.

Har du en DevOps i ditt team? (SWE)

Vill du kunna leverera mjukvara snabbare utan att förlora kvalitet? Då ska du komma till vårt seminarium om DevOps där vi förklarar hur denna roll kan hjälpa teamet styra upp sina leveranser så flödet från utveckling till test till produktion flyter på ett effektivt sätt.

Vi baserar såklart lösningen på senaste tekniker från Microsoft, bland annat Visual Studio 2013, TFS 2013, Microsoft Azure, PowerShell och Microsoft Release Management.

Den 10 juni kör vi i Stockholm och 12 september i Göteborg.

För mer information och bokning: http://informator.se/seminarier/seminarier/har-du-en-devops-i-ditt-team

image

New book: Team Foundation Server 2013 Customization

I had the pleasure reviewing this great book on TFS customization by Gordon Beeming. It’s a short book (just the way we come to expect from the PACKT series) but it covers a big topic and in a very efficient way. Just look at the TOC:

  • Customizing TFS process templates
  • Customizing TFS Web Access
  • Creating custom work item controls
  • Creating service-side plugins
  • Creating TFS scheduled jobs
  • Customizing the TFS Build process

Not bad for a 82 pages book! I warmly recommend this nugget to anyone interested in learning more about how to extend and customize a TFS server.

image

Read more and order: http://www.amazon.com/Team-Foundation-Server-2013-Customization-ebook/dp/B00HYTDXJU

Thoughts on Visual Studio ALM