Sunday, April 14, 2013

How To Create a Test Plans and Cases Migration Tool For TFS : Part 1

Recently We had to move some team projects from TFS 2010 Server to a newly created TFS 2012 Server. This involves moving all source files,work items, attachments, links and team queries. Though moving source files is an easy task, moving work items is not an easy feat. This is due to many reasons. Such as TFS 2010 use the Scrum 1.0 template and TFS 2012  use Scrum 2.0 template(Update 2 use 2.2 template). Migration is done through the APIs of TFS by using external tools, and is a lossy data transfer. There is a migration tool named TFS Integration Tools developed by TFS product group  and the Visual Studio ALM Rangers. This product is not 100% generic and it has certain limitations; such as not supporting test case migration, permission, etc. Therefore we decided to built a much more generic tool that match our need.



As a part of the process We had to transfer all the Test Plans, Test suits and associated test cases. These Test plans and suits are built and maintained using Microsoft Test Manager. I build a tool which enables migrate test plans from one project to another.(projects may be reside in one project collection or or may be reside on two servers) For this task I had to use Test Management API  in order to add Test Plan programmatically. With the API anyone could create their own solution or a custom tool that fits their individual needs for migrating data between systems.  


Before creating tool,first of all let's get an idea about how to create and edit test plans, suits and test cases.


You’ll need to add references to the following assemblies to your project.

  • Microsoft.TeamFoundation.Client.dll 
  • Microsoft.TeamFoundation.TestManagement.Client.dll 
  • Microsoft.TeamFoundation.TestManagement.Common.dll 
  • Microsoft.TeamFoundation.WorkItemTracking.Client.dll 
These assemblies are located at:C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0

Step 1: Connect to Team Foundation Server

string sourceserverurl = "http://localhost:8080/tfs/defaultcollection";
string sourceproject = "General";

ITestManagementTeamProject project = GetProject(sourceserverurl, sourceproject);


ITestManagementTeamProject GetProject(string serverUrl, string project)
{
  TfsTeamProjectCollection tfs = new  TfsTeamProjectCollection(TfsTeamProjectCollection.GetFullyQualifiedUriForName(serverUrl));
  ITestManagementService tms = tfs.GetService<ITestManagementService>();

   return tms.GetTeamProject(project);
}


Step 2: Create a Test Plan Programmatically
            
            ITestPlan plan = project.TestPlans.Create();
            plan.Name = " First Test Plan";
            plan.StartDate = DateTime.Now;
            plan.EndDate = DateTime.Now.AddMonths(2);
            // other attributes: plan.AreaPath, plan.Description,plan.State
            plan.Save();

Step 3: Create a Test Suite Programmatically
          
            IStaticTestSuite newSuite = project.TestSuites.CreateStatic();
            newSuite.Title = "Test Suite";        
            plan.RootSuite.Entries.Add(newSuite);
            plan.Save();

Step 4: Create a Test Case Programmatically
           
            ITestCase tc = project.TestCases.Create();
            tc.Title = "Test case 1";
            tc.Save();
            newSuite.Entries.Add(tc);
            plan.Save();

Step 5: List all Test Plans
           
            foreach (ITestPlan p in project.TestPlans.Query("Select * From TestPlan"))
            {
                Console.WriteLine("Plan - {0} : {1}", p.Id, p.Name);
            }

Additional: Delete a Test Plan

            plan.Delete(DeleteAction.ForceDeletion);

Step 6: List all test suits and test cases.

foreach (ITestSuiteBase suite in plan.RootSuite.SubSuites)
{
     Console.WriteLine("\tTest Suite: {0}", suite.Title);

     IStaticTestSuite staticSuite = suite as IStaticTestSuite;

     // Let's Query the Test Points.
    foreach(ITestPoint point in plan.QueryTestPoints(
                    string.Format("SELECT * FROM TestPoint WHERE SuiteId = {0}",
                    suite.Id)))
    {
                    Console.WriteLine("\t\tTest Point for Testcase \"{0}\" against config \"{1}\"",
                        point.TestCaseWorkItem.Title, point.ConfigurationName);                        
     }
}

Full Code:

namespace TFSMigrationApp
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            string sourceserverurl = "http://localhost:8080/tfs/defaultcollection";
            string sourceproject = "General";

            ITestManagementTeamProject project = GetProject(sourceserverurl, sourceproject);

            // List all Test Plans before adding new plan
            foreach (ITestPlan p in project.TestPlans.Query("Select * From TestPlan"))
            {
                Console.WriteLine("Plan - {0} : {1}", p.Id, p.Name);
            }

            // creating a new Test Plan from scratch
            ITestPlan plan = project.TestPlans.Create();
            plan.Name = "My New Test Plan";
            plan.StartDate = DateTime.Now;
            plan.EndDate = DateTime.Now.AddMonths(2);
            plan.Save();

            Console.WriteLine("Created new Plan \"{0}\" with Id: {1}",
                plan.Name, plan.Id);

            //addding a new Test Suite to our plan
            IStaticTestSuite newSuite = project.TestSuites.CreateStatic();
            newSuite.Title = "Test Suite";         
            plan.RootSuite.Entries.Add(newSuite);
            plan.Save();

            // creating a Testcase to add to our Test Suite
            ITestCase tc = project.TestCases.Create();
            tc.Title = "Test case 1";
            tc.Save();
            newSuite.Entries.Add(tc);
            plan.Save();


            // List all Test Plans
            foreach (ITestPlan p in project.TestPlans.Query("Select * From TestPlan"))
            {
                Console.WriteLine("Plan - {0} : {1}", p.Id, p.Name);
            }

            //List all test suits and test cases.
            foreach (ITestSuiteBase suite in plan.RootSuite.SubSuites)
            {
                Console.WriteLine("\tTest Suite: {0}", suite.Title);

                IStaticTestSuite staticSuite = suite as IStaticTestSuite;

                // Let's Query the Test Points.
                foreach (ITestPoint point in plan.QueryTestPoints(
                    string.Format("SELECT * FROM TestPoint WHERE SuiteId = {0}",
                    suite.Id)))
                {
                    Console.WriteLine("\t\tTest Point for Testcase \"{0}\" against config \"{1}\"",
                        point.TestCaseWorkItem.Title, point.ConfigurationName);                        
                }
            }
        }

        static ITestManagementTeamProject GetProject(string serverUrl,
           string project)
        {
            TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(TfsTeamProjectCollection.GetFullyQualifiedUriForName(serverUrl));
            ITestManagementService tms = tfs.GetService<ITestManagementService>();

            return tms.GetTeamProject(project);
        }

       
    }
}

5 comments:

  1. The mostly sense of your content is programming type. information about the topic is superb but you can't share the information about server migration project plan. Share the all views about these type of project planings.

    ReplyDelete
  2. Thanks for the compliment David.Your right, sure there is lot of ways to migrate projects and contents. such as migrating vs upgrading trade-offs. But I just wan't to show how a programmer can build a own tool to suit his requirements(in this case test plans). That's why I wrote the article in a programmers point of view. once again thanks or the feedback.

    ReplyDelete
  3. Thank you for writing these articles! Do you know how to programmatically delete test cases. ITestCase doesn't seem to have Delete() like ITestPlan

    ReplyDelete
  4. Unlike Test Plans and suits Test cases are Work Items, therefore you have to use work item tracking api to delete test cases. so first get test case work item id (testcase.WorkItem.Id) and try this link to delete items, http://social.msdn.microsoft.com/Forums/vstudio/en-US/b8a01ae9-70ca-4f11-b5e0-5b565b8ed8a1/how-to-delete-workitem-programmatically?forum=tfsworkitemtracking
    hope this will help you.

    ReplyDelete
  5. Thanks Asanka and could you please share how to create the Bug in tfs.

    ReplyDelete