在TFS API中,如何获取给定测试的完整类名?

我手头有一个ITestCaseResult对象,我无法弄清楚如何从中提取Test Class信息。 该对象包含TestCaseTitle属性中的测试方法名称,但我们的代码库中有很多重复的标题,我想了解更多信息。

假设我有类Baz和方法ThisIsATestMethod Foo.Bar程序集,我目前只能从标题中访问ThisIsATestMethod信息,但我想获得Foo.Bar.Baz.ThisIsATestMethod

如何使用TFS API执行此操作?

这是一些精简代码:

 var def = buildServer.CreateBuildDetailSpec(teamProject.Name); def.MaxBuildsPerDefinition = 1; def.QueryOrder = BuildQueryOrder.FinishTimeDescending; def.DefinitionSpec.Name = buildDefinition.Name; def.Status = BuildStatus.Failed | BuildStatus.PartiallySucceeded | BuildStatus.Succeeded; var build = buildServer.QueryBuilds(def).Builds.SingleOrDefault(); if (build == null) return; var testRun = tms.GetTeamProject(teamProject.Name).TestRuns.ByBuild(build.Uri).SingleOrDefault(); if (testRun == null) return; foreach (var outcome in new[] { TestOutcome.Error, TestOutcome.Failed, TestOutcome.Inconclusive, TestOutcome.Timeout, TestOutcome.Warning }) ProcessTestResults(bd, testRun, outcome); 

 private void ProcessTestResults(ADBM.BuildDefinition bd, ITestRun testRun, TestOutcome outcome) { var results = testRun.QueryResultsByOutcome(outcome); if (results.Count == 0) return; var testResults = from r in results // The "r" in here is an ITestCaseResult. r.GetTestCase() is always null. select new ADBM.Test() { Title = r.TestCaseTitle, Outcome = outcome.ToString(), ErrorMessage = r.ErrorMessage }; } 

您可以通过从TFS下载TRX文件并手动解析来完成此操作。 要下载测试运行的TRX文件,请执行以下操作:

  TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://my-tfs:8080/tfs/DefaultCollection")); ITestManagementService tms = tpc.GetService(); ITestManagementTeamProject tmtp = tms.GetTeamProject("My Project"); ITestRunHelper testRunHelper = tmtp.TestRuns; IEnumerable testRuns = testRunHelper.ByBuild(new Uri("vstfs:///Build/Build/123456")); var failedRuns = testRuns.Where(run => run.QueryResultsByOutcome(TestOutcome.Failed).Any()).ToList(); failedRuns.First().Attachments[0].DownloadToFile(@"D:\temp\myfile.trx"); 

然后解析TRX文件(XML),查找元素,该元素包含“className”属性中的完全限定类名:

  

由于测试用例的详细信息存储在工作项中,因此您可以通过访问测试用例的工作项来获取数据

 ITestCaseResult result; var testCase = result.GetTestCase(); testCase.WorkItem["Automated Test Name"]; // fqdn of method testCase.WorkItem["Automated Test Storage"]; // dll 

在这里,您可以获得程序集名称:

  foreach (ITestCaseResult testCaseResult in failures) { string testName = testCaseResult.TestCaseTitle; ITmiTestImplementation testImplementation = testCaseResult.Implementation as ITmiTestImplementation; string assembly = testImplementation.Storage; } 

不幸的是, ITestCaseResultITmiTestImplementation似乎不包含测试用例的命名空间。

检查此链接中的最后一个响应, 这可能会有所帮助。 祝好运!

编辑 :这是基于查尔斯克莱恩的答案,但获得类名而无需下载到文件:

  var className = GetTestClassName(testResult.Attachments); 

方法本身:

  private static string GetTestClassName(IAttachmentCollection attachmentCol) { if (attachmentCol == null || attachmentCol.Count == 0) { return string.Empty; } var attachment = attachmentCol.First(att => att.AttachmentType == "TmiTestResultDetail"); var content = new byte[attachment.Length]; attachment.DownloadToArray(content, 0); var strContent = Encoding.UTF8.GetString(content); var reader = XmlReader.Create(new StringReader(RemoveTroublesomeCharacters(strContent))); var root = XElement.Load(reader); var nameTable = reader.NameTable; if (nameTable != null) { var namespaceManager = new XmlNamespaceManager(nameTable); namespaceManager.AddNamespace("ns", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010"); var classNameAtt = root.XPathSelectElement("./ns:TestDefinitions/ns:UnitTest[1]/ns:TestMethod[1]", namespaceManager).Attribute("className"); if (classNameAtt != null) return classNameAtt.Value.Split(',')[1].Trim(); } return string.Empty; } internal static string RemoveTroublesomeCharacters(string inString) { if (inString == null) return null; var newString = new StringBuilder(); foreach (var ch in inString) { // remove any characters outside the valid UTF-8 range as well as all control characters // except tabs and new lines if ((ch < 0x00FD && ch > 0x001F) || ch == '\t' || ch == '\n' || ch == '\r') { newString.Append(ch); } } return newString.ToString(); }