Jaa


TFS: Programatically importing testcase results to MTM

This post is intended to provide a detailed approach to importing testcase results from a source/system to Microsoft Test Manager associated with TFS.

You will need to process data from your system/source which you can then add to MTM. An XML file source with Axe IDs and corresponding results has been used as an example in this post. Each AXE Id should map to a test points in TFS for the result to be created/saved.
Note : Test Points and Test cases are treated differently by MTM. Each Testcase can be run with a number of configurations and each combination of test case and configuration is called a test point. When creating a test run, we will use test points as tests are executed and results are stored against test points and not test cases.

The overall approach can be broken down into a couple of tasks:

1. Reading/Storing test result data from your system into some form/structure.

2. Establishing connection to TFS

3. Identifying test points which correspond to the results from our source.

4. Adding results corresponding to the test points and uploading them to TFS

 The following assemblies will be needed for the operations below:
System;
System.Net;

System.Linq;
System.Text;
System.Xml;
System.Collections.Generic;
Microsoft.TeamFoundation.Client;

Microsoft.TeamFoundation.TestManagement.Client;
Microsoft.TeamFoundation.TestManagement.Common;Microsoft.TeamFoundation.WorkItemTracking.Client;

Part I:

For the first part, an xml file with AXE Ids and corresponding results will be processed for storing data in a more usable form. Here, a dictionary is created with the key as the Axe Id which is the Id which will be used to identify the test point in TFS.

  //Dictionary to store the Axe Ids and corresponding results from the MTM xml file
Dictionary<string, TestPointResultData> test_point_result_dictionary = new Dictionary<string, TestPointResultData>();
             

  // Create an instance of XmlTextReader and call Read method to read the file
XmlTextReader textReader = null;
textReader = new XmlTextReader(<xml-file-path>);
textReader.Read();
//< write your own code ro read the XML bits which contain the Ids and results data and store them in the dictionary>

A class TestPointResultData has been used to store result data correspoding to the Axe ID. The details of the class are as below:

class TestPointResultData
{
// Field to store the test point outcomepublicString Outcome { get; set
; }publicbool hasTestPoint { get; set; }

// Field to store the info about failurepublicString Info { get; set
; }public TestPointResultData(String outcome, bool foundTestPoint, String info = null
) }

Part II:
Now that the data to be inserted into TFS has been identified and stored, establish a connection to TFS.

 string serverurl = " https://<tfs-server-name>:<port-number>/tfs ";
TeamFoundationServer tfs = new TeamFoundationServer(serverurl, new UICredentialsProvider());
// Or use this for entering credentials via code and avoiding UI prompt: tfs = new TeamFoundationServer(tfServerName, '''new NetworkCredential("User", "Password", "Domain");
// Ensure the current user can authenticate with TFS
tfs.EnsureAuthenticated();

TfsTeamProjectCollection tfsCollection = new TfsTeamProjectCollection(TfsTeamProjectCollection.GetFullyQualifiedUriForName(serverurl));
ITestManagementService tms = tfs.GetService<ITestManagementService>();
ITestManagementTeamProject project = tms.GetTeamProject(<project-name>);
ITestPlanHelper planHelper = project.TestPlans;
ITestPlan foundPlan = project.TestPlans.Find(<test-plan-number>);
 

The test plan where the results are to be inserted has now been retrieved.

Part III:
To be able to add results to this test plan, create a new test run in the test plan. map the test points which are present in the dictionary and add to this test run. Ideally, you should be able to add the results while adding the test point to the run but the run.Save() API is only working for single Save right now. So, you will need to add all the testpoints, save the test run and then iterate over the run collection to add results individually. For better performance, save the result collection once after all the results have been added/updated.

//create a test run
ITestRun run = foundPlan.CreateTestRun(true);
run.Title = <custom-title>
foreach (ITestSuiteBase suite in foundPlan.RootSuite.SubSuites)
{
IStaticTestSuite staticSuite = suite as IStaticTestSuite;
ITestPointCollection testPoints = foundPlan.QueryTestPoints(string.Format("SELECT * FROM TestPoint WHERE SuiteId = {0}", suite.Id));
int number = testPoints.Count;
System.Linq.IQueryable<ITestPoint> linqQuery = testPoints.AsQueryable();
foreach (string testID in test_point_result_dictionary.Keys)
{
if (test_point_result_dictionary[testID].hasTestPoint) continue;

  // Use linq query to find the test point correspoding to each AXE Id.
var mytestPoint = linqQuery.Where(point => point.TestCaseWorkItem.Implementation.DisplayText.Contains(testID));
foreach (ITestPoint tp in mytestPoint)
{
run.AddTestPoint(tp, null);
}
}
}

//save the added testpoints in this test run
run.Save();

Part IV:
Test Run with required test points has been created. Adding results:

ITestCaseResultCollection resultCollection = run.QueryResults();
foreach( ITestCaseResult result1 in resultCollection)
{
ITestCase testcase = result1.GetTestCase();
string displayText = testcase.Implementation.DisplayText;
string[] displayTextArray = displayText.Split('.');
string axeID = displayTextArray[displayTextArray.Count()-1];
TestPointResultData value;
if (null != axeID && test_point_result_dictionary.TryGetValue(axeID, out value))
{
result1.State = TestResultState.Completed;
switch (value.Outcome)
{
case "Pass": result1.Outcome = TestOutcome.Passed; break;
case "Fail": result1.Outcome = TestOutcome.Failed; break;
// add other cases
}
}
}

//save the result collection once in the end.
resultCollection.Save(false);

Once the result collection is saved, you should be able to see this test run and corrresponding results in TFS/MTM under Test->Analyse Test Runs. To keep this blog simple and focus on the approach, most the error handling has been ommited.

Finally, to see the results that have been added to TFS, you can interate over the result collection:

//Iterate over results to diplay the Recorded results
foreach (ITestCaseResult result1 in resultCollection)
{
ITestCase testcase = result1.GetTestCase();
Console.WriteLine("Testcase {0} Outcome {1}", testcase.Implementation.DisplayText, result1.Outcome);
}