如何通过REST API将.trx测试结果发布至TFS 2018测试用例
用TFS REST API替代tcm.exe发布.trx测试结果到指定测试套件
我完全理解你的困惑——TFS的测试管理API文档确实有点零散,尤其是Test Run和Test Point的概念,刚接触很容易懵。我来帮你理清这些核心概念,然后给一个贴合你场景的完整示例,一步步从.trx文件把结果发布到指定测试套件的关联用例里。
先搞懂核心概念:Test Run vs Test Point
先把这两个概念掰明白,后面的逻辑就通了:
- Test Run:对应你用
mstest.exe跑一次自动化测试的"整体执行记录",相当于tcm.exe里的一次发布批次,它包含这次执行的所有测试用例结果。 - Test Point:这是关键——它是测试用例在「特定测试套件+特定测试配置」下的实例。举个例子:同一个测试用例如果被加到两个测试套件,或者有2种不同的测试配置(比如Windows 10/Windows 11),就会生成多个Test Point。当你执行这个用例时,其实是把结果关联到对应的Test Point上。
划重点:你不需要手动创建Test Point!当你把测试用例添加到测试套件、并配置好测试配置(默认会有一个)后,TFS会自动生成对应的Test Point。我们要做的只是找到这些Point,把结果挂上去。
完整实现步骤(.NET示例)
我用Microsoft.TeamFoundation.TestManagement.WebApi客户端来写示例,这是官方推荐的方式,比直接调用REST URL更省心。首先需要安装NuGet包:
Install-Package Microsoft.TeamFoundationServer.Client
步骤1:初始化TFS客户端
先建立和TFS服务器的连接:
using Microsoft.TeamFoundation.Core.WebApi; using Microsoft.TeamFoundation.TestManagement.WebApi; using Microsoft.VisualStudio.Services.Common; using Microsoft.VisualStudio.Services.WebApi; // 替换成你的TFS地址、集合名 var tfsUri = new Uri("http://your-tfs-server:8080/tfs/YourCollectionName"); var credentials = new VssCredentials(); // 如果是域账号,用new WindowsCredential()即可 // 初始化连接和测试管理客户端 var connection = new VssConnection(tfsUri, credentials); var testClient = connection.GetClient<TestManagementHttpClient>();
步骤2:解析.trx文件提取测试结果
.trx本质是XML文件,你可以用Microsoft.VisualStudio.TestPlatform.ObjectModel里的类来解析,或者自己用XDocument读取。这里用官方类库示例:
using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using System.Xml; // 替换成你的.trx文件路径 var trxFilePath = @"C:\AutomationTests\Results\TestRun_20240520.trx"; // 解析.trx TestRun testRun; using (var reader = XmlReader.Create(trxFilePath)) { testRun = TestRun.Deserialize(reader); } // 提取关键信息:这里假设你的自动化用例名称包含TFS测试用例ID(比如"TC1234_LoginTest") var automatedResults = new List<(int TestCaseId, TestOutcome Outcome, string ErrorMsg, DateTime CompletedTime)>(); foreach (var result in testRun.Results) { // 从用例名称中提取TFS测试用例ID,你可以根据自己的命名规则调整正则 var match = System.Text.RegularExpressions.Regex.Match(result.TestCaseName, @"TC(\d+)"); if (match.Success && int.TryParse(match.Groups[1].Value, out int tcId)) { automatedResults.Add(( tcId, result.Outcome, result.ErrorMessage, result.EndTime )); } }
步骤3:查询目标测试套件下的Test Points
我们需要找到目标测试套件里,所有关联测试用例对应的Test Point:
// 替换成你的项目ID(可以从TFS项目设置里复制)和测试套件ID var projectId = "your-project-guid-here"; var targetTestSuiteId = 456; // 你要发布结果的测试套件ID // 查询该测试套件下的所有Test Point var testPointsQuery = new TestPointQueryCriteria { SuiteIds = new[] { targetTestSuiteId }, IncludePointDetails = true // 要获取完整的Point信息,比如关联的测试用例ID }; var testPoints = await testClient.GetTestPointsAsync(projectId, testPointQueryCriteria: testPointsQuery); // 构建「测试用例ID → Test Point」的映射,方便后续匹配 var tcIdToTestPointMap = testPoints.ToDictionary(p => p.TestCase.Id, p => p);
步骤4:创建Test Run并上传结果
先创建一个Test Run,然后把.trx里的结果关联到对应的Test Point上:
// 1. 创建Test Run var newRun = new RunCreateModel { Name = $"Automated Test Run - {DateTime.Now:yyyy-MM-dd HH:mm:ss}", PlanId = testPoints.First().Plan.Id, // 从Test Point里取所属的测试计划ID State = RunState.Completed, // 直接标记为完成,因为我们已经有全部结果了 AutomationName = "MSTest", // 标记自动化类型 }; var createdRun = await testClient.CreateTestRunAsync(newRun, projectId); // 2. 准备要提交的测试结果 var resultsToSubmit = new List<TestCaseResultCreateUpdateParameters>(); foreach (var (tcId, outcome, errorMsg, completedTime) in automatedResults) { if (tcIdToTestPointMap.TryGetValue(tcId, out var testPoint)) { resultsToSubmit.Add(new TestCaseResultCreateUpdateParameters { TestPointId = testPoint.Id, // 关联到对应的Test Point Outcome = outcome.ToString(), State = TestResultState.Completed, ErrorMessage = errorMsg, CompletedDate = completedTime }); } else { Console.WriteLine($"Warning: 测试用例ID {tcId} 未在目标测试套件中找到对应的Test Point"); } } // 3. 提交结果到Test Run await testClient.AddTestResultsToTestRunAsync(resultsToSubmit, projectId, createdRun.Id);
关键注意事项
- 权限问题:确保你的账号拥有「测试计划编辑」和「测试结果提交」的权限,否则API会返回403错误。
- 测试配置匹配:如果你的测试用例有多个测试配置(比如不同环境),查询Test Point时要加上
ConfigIds参数,确保拿到对应配置的Point。 - 批量提交:如果你的测试结果很多(比如几百个),建议分成批次提交(比如每50个一批),避免API请求过大被限流。
- 用例关联规则:示例里用了「自动化用例名称包含TFS用例ID」的规则,你也可以用TestCategory、或者在自动化代码里通过Attribute标记TFS用例ID,只要能准确匹配到即可。
内容的提问来源于stack exchange,提问作者Choub890
相关产品推荐
相关产品推荐

