Extract TFS 2012 build unit test results - tfs

Does anyone know of a way to quickly get at the unit test results of a build in TFS2012?
Currently I have to find the build in visual studio and collapse the various other nodes in the summary as shown in the screenshot below. Then I have to expand each set of results to get at the failures. I just want a list of all failed tests.
I'd be happy to use SQL, SQL Reporting services or even a text file from the build.
Thanks

You can use TFS API to get the test result. Check the code snippet below:
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri("http://tfsserver:8080/tfs/collectionname"));
tfs.EnsureAuthenticated();
IBuildServer tfsBuildServer = tfs.GetService<IBuildServer>();
IBuildDefinition buildDef = tfsBuildServer.GetBuildDefinition("teamproject", "project");
var BuildUri = buildDef.LastBuildUri;
ITestManagementService testManagement = (ITestManagementService)tfs.GetService(typeof(ITestManagementService));
ITestManagementTeamProject testManagementTeamProject = testManagement.GetTeamProject("teamproject");
IEnumerable<ITestRun> testRuns = testManagementTeamProject.TestRuns.ByBuild(BuildUri);
foreach (ITestRun testRun in testRuns)
{
foreach (ITestCaseResult result in testRun.QueryResults())
{
Console.WriteLine(string.Format("TestCaseID:{0}", result.TestCaseTitle.ToString()));
Console.WriteLine(string.Format("TestCaseOutcome:{0}", result.Outcome.ToString()));
}
}

Related

TFS API and report performance: get test case results by test plan?

In a report, I need to present all test results for a certain test plan.
Currently I am using the following function:
foreach (TestCase testCase in testCasesByWorkItem)
{
List<ITestCaseResult> testCaseResults = teamProject.TestResults.ByTestId(testCase.TestCaseId).Where(x => x.State == TestResultState.Completed).ToList();
....
}
My understanding is that it returns all results for this test case, and one test case may belong to many test plans.
My problem is performance. The operation takes up to 25 seconds (in debug mode), and I have thousands of test cases.
I only need those test case results, that belong to a certain test plan.
For example, TestCaseX may have been executed for test plans Release1.0, Release2.0, .... Release20.0. And I am only interested in results for Release15.0.
Currently I retrieve results as above, and later filter by a correct test plan.
Is there a way to optimize performance by somehow only selecting test results that belong to a given test plan?
You can use below sample to get test runs against a test plan id:
TfsTeamProjectCollection tfctc = new TfsTeamProjectCollection(new Uri("http://tfsservername:8080/tfs/DefaultCollection"));
ITestManagementService testmanagementService = tfctc.GetService<ITestManagementService>();
var teamproject = testmanagementService.GetTeamProject("teamprojectname");
var testruns = testmanagementService.QueryTestRuns("select * From TestRun");
List<ITestRun> testrunInPlan = new List<ITestRun>();
foreach (var testrun in testruns)
{
if (testrun.TestPlanId==31) // in this case TestPlanId is 31
{
testrunInPlan.Add(testrun);
}
}
And below sample to get test case result for a particular test run:
ITestCaseResultCollection testcases = testrun.QueryResults();
foreach (ITestCaseResult testcase in testcases)
{
Console.WriteLine("TestCase ID: " + testcase.TestCaseId);
Console.WriteLine("TestCase Title: " + testcase.TestCaseTitle);
Console.WriteLine("Error Message: " + testcase.ErrorMessage);
}
Please check this blog for the details on Test Management API: http://blogs.msdn.com/b/aseemb/archive/2012/08/07/code-snippets-on-test-management-apis.aspx
You might find using the TFS Rest API useful for what you are trying to do.
https://www.visualstudio.com/en-us/docs/integrate/api/test/runs
You will be able to get the list of all test runs for the given planId using the first API listed on the page and then use the runId to get all test returns using the Test results API
https://www.visualstudio.com/en-us/docs/integrate/api/test/results_1_0
Personally, I find using the API's a lot easier than working with the object model.

how to search build definitions in TFS those are no longer in use?

Can anyone help me to understand the below query,Actually in our tfs we have huge number of build definition those are not in use so far hence i want to delete old build definition by seraching all the builds those are older more than one year.
how to search build definitions in TFS2013 those are no longer in use??
Please help.
Thanks,
You can query out the definitions those are older more than one year by this query in SQL Server.
SELECT [DefinitionId],[DefinitionVersion],[DefinitionName] FROM [Tfs_CollectionLC].[Build].[tbl_Definition]
WHERE [CreatedOn] < '2016-06-12 00:00:00.000'
But for the definitions are no longer in use, you have to get the last build for each definition and check whether the build FinishTime is before a year ago (Where [FinishTime] < '2016-06-12 00:00:00.000' ).
You can use TFS API/Client API to get the build details which including the build FinishTime, then filter them accordingly.You can reference below code which enumerates each team project and gets the latest build status for each of the definitions:
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri("http://tfs:8080"));
var vcs = tfs.GetService<VersionControlServer>();
var teamProjects = vcs.GetAllTeamProjects(true);
IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
foreach (TeamProject proj in teamProjects)
{
var defs = buildServer.QueryBuildDefinitions(proj.Name);
System.Console.WriteLine(string.Format("Team Project: {0}", proj.Name));
foreach(IBuildDefinition def in defs)
{
IBuildDetailSpec spec = buildServer.CreateBuildDetailSpec(proj.Name, def.Name);
spec.MaxBuildsPerDefinition = 1;
spec.QueryOrder = BuildQueryOrder.FinishTimeDescending;
var builds = buildServer.QueryBuilds(spec);
if (builds.Builds.Length > 0)
{
var buildDetail = builds.Builds[0];
System.Console.WriteLine(string.Format(" {0} - {1} - {2}", def.Name, buildDetail.Status.ToString(), buildDetail.FinishTime));
}
}
System.Console.WriteLine();
}
Reference this thread:TFS API - How to query builds independent of which build definition they belong to
Update: Based on #Dhurva's comments below:
We can also use the utility from github TFS Manager that finds all build definition from team project:
https://github.com/jelledruyts/TfsTeamProjectManager

How do I find TFS builds by controller used to build it?

Here is my code:
var tfs = new TfsTeamProjectCollection(new Uri(TFS_SERVER_URL));
tfs.EnsureAuthenticated();
var buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
var spec = buildServer.CreateBuildDetailSpec(projectName);
spec.QueryOrder = BuildQueryOrder.FinishTimeDescending;
spec.MinFinishTime = DateTime.Now.Subtract(minFinishTimeOfs);
spec.MaxFinishTime = DateTime.Now.Subtract(maxFinishTimeOfs);
if (reason != null)
{
spec.Reason = reason.Value;
}
var buildDetails = buildServer.QueryBuilds(spec).Builds;
As you can see, I know how to query by time and build reason. But I want to be able to query by the build controller and I do not see how to do it efficiently. The inefficient way is to get the builds across all the build controllers and then filter them out, but I would like to avoid fetching irrelevant build details in the first place.
There is no API to judge from build definition to get IBuildDetail builds. As you mentioned above, you have to get firstly get all builds, and filter out unwanted builds with the IBuildDetail.BuildControllerUri property.

How to merge TFS change sets programmatically?

I know how to merge a change set in TFS 2010 using the command line command "tf merge".
Is there a way I can do this in C# with code. I want to merge specific change sets only (cherry pick), one at a time.
This is roughly how you would do it if you were working with the 2010 or 2012 TFS object models. Let me know if you have any questions.
// Get a reference to yourTeam Foundation Server.
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://<yourserver>:8080/tfs/<yourcollection> "));
// Get a reference to Version Control.
VersionControlServer versionControl = tpc.GetService<VersionControlServer>();
Workspace workspace = versionControl.GetWorkspace("<local path to your workspace>");
string sourceBranch = "$/<sourceBranch>";
string targetBranch = "$/<targetBranch>";
VersionSpec changesetToMerge = new ChangesetVersionSpec(<your changeset here>);
// actually pend the merge
workspace.Merge(sourceBranch, targetBranch, changesetToMerge, changesetToMerge);
// check in the merge
workspace.CheckIn(workspace.GetPendingChanges(), "your comment");

How can I copy a TFS 2010 Build Definition?

Is there any way to copy a build definition? I work in a mainline source control methodology which utilizes many different branches that live for very short periods (ie. a few days to a week). I'd really like to copy a build template and just change the solution to build. Is there any way to do this?
You can download the new TFS 2010 power tools. It has the option to clone a build definition.
See http://msmvps.com/blogs/molausson/archive/2010/10/21/clone-a-build-definition.aspx for an example
Note: Be aware that the Clone only works when you did NOT pop out the Build window.
You can write an add-in to do it. Here's the code to copy an existing build definition:
static IBuildDefinition CloneBuildDefinition(IBuildDefinition buildDefinition)
{
var buildDefinitionClone = buildDefinition.BuildServer.CreateBuildDefinition(
buildDefinition.TeamProject);
buildDefinitionClone.BuildController = buildDefinition.BuildController;
buildDefinitionClone.ContinuousIntegrationType = buildDefinition.ContinuousIntegrationType;
buildDefinitionClone.ContinuousIntegrationQuietPeriod = buildDefinition.ContinuousIntegrationQuietPeriod;
buildDefinitionClone.DefaultDropLocation = buildDefinition.DefaultDropLocation;
buildDefinitionClone.Description = buildDefinition.Description;
buildDefinitionClone.Enabled = buildDefinition.Enabled;
buildDefinitionClone.Name = String.Format("Copy of {0}", buildDefinition.Name);
buildDefinitionClone.Process = buildDefinition.Process;
buildDefinitionClone.ProcessParameters = buildDefinition.ProcessParameters;
foreach (var schedule in buildDefinition.Schedules)
{
var newSchedule = buildDefinitionClone.AddSchedule();
newSchedule.DaysToBuild = schedule.DaysToBuild;
newSchedule.StartTime = schedule.StartTime;
newSchedule.TimeZone = schedule.TimeZone;
}
foreach (var mapping in buildDefinition.Workspace.Mappings)
{
buildDefinitionClone.Workspace.AddMapping(
mapping.ServerItem, mapping.LocalItem, mapping.MappingType, mapping.Depth);
}
buildDefinitionClone.RetentionPolicyList.Clear();
foreach (var policy in buildDefinition.RetentionPolicyList)
{
buildDefinitionClone.AddRetentionPolicy(
policy.BuildReason, policy.BuildStatus, policy.NumberToKeep, policy.DeleteOptions);
}
return buildDefinitionClone;
}
The following tool (VS Addin) will satisfy your requirement>
Community TFS Build Manager
http://visualstudiogallery.msdn.microsoft.com/16bafc63-0f20-4cc3-8b67-4e25d150102c
I just had a need to copy build definitions, and found Jim's answer above to be helpful. However, being new to the TFS API, I needed help connecting to the server and getting the existing build definition through code. These two links helped fill in the gaps:
http://msdn.microsoft.com/en-us/library/bb286958.aspx
http://geekswithblogs.net/jakob/archive/2010/04/26/creating-a-build-definition-using-the-tfs-2010-api.aspx
You can right click the build definition and select 'clone build definition' to copy the definition file. You can then edit it from there.
Here is the soltion if you want to move the Build definition from one Team Project to other Team project.
public void MoveBuild(string fromTeamProject, string toTeamProject, string buildName, string newBuildName)
{
var _server = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new
Uri("http://Mytfs:8080/defaultcollection"));
IBuildServer _buildServer = _server.GetService<IBuildServer>();
var buildDetails = _buildServer.QueryBuildDefinitions(fromTeamProject);
foreach (var fromBuild in buildDetails)
{
if (fromBuild.Name != buildName) continue;
var newBuildDefinition = _buildServer.CreateBuildDefinition(toTeamProject);
newBuildDefinition.Name = !string.IsNullOrEmpty(newBuildName) ? newBuildName : fromBuild.Name;
newBuildDefinition.BuildController = fromBuild.BuildController;
// This finds the template to use
foreach (var mapping in fromBuild.Workspace.Mappings)
{
newBuildDefinition.Workspace.AddMapping(
mapping.ServerItem, mapping.LocalItem, mapping.MappingType, mapping.Depth);
}
newBuildDefinition.DefaultDropLocation = fromBuild.DefaultDropLocation;
newBuildDefinition.Description = fromBuild.Description;
// buildDefinition.Workspace.AddMapping(build.Workspace.);
newBuildDefinition.Process = _buildServer.QueryProcessTemplates(fromBuild)[2];
newBuildDefinition.ProcessParameters = fromBuild.ProcessParameters;
newBuildDefinition.Enabled = false;
newBuildDefinition.Save();
}//end of for each loop
}
From your message it is not clear which template is your build definition using (default, upgrade or lab management). If I understand correctly you would like to easily set up a build definition which builds the same solution but from a different branch.
One thing that you could try instead of copying the definition is to edit it. When the branch dies, rename the build definition (might help with reporting), change the workspace mapping of the build and you should be done.
Thanks, Ladislau

Resources