使用Azure DevOps REST API 6.0-preview.1添加TestSubResult遇ID获取难题
如何获取Azure DevOps测试子结果ID(TestSubResultId)以添加附件
问题背景
已成功为TestResult添加附件,但在给TestSubResult添加附件时,POST接口要求传入testSubResultId参数,不清楚该ID的获取方式;用随机数替代时,程序无报错但直接终止执行。使用的POST接口为:
https://dev.azure.com/{organization}/{project}/_apis/test/Runs/{runId}/Results/{testCaseResultId}/attachments?testSubResultId={testSubResultId}&api-version=6.0-preview.1
请求体对应的C#类结构:
public class TestSubResultRequest { public string AttachmentType { get; set; } public string Comment { get; set; } public string FileName { get; set; } public string Stream { get; set; } }
获取TestSubResultId的正确方式
要拿到有效的testSubResultId,必须调用测试结果详情查询接口,并携带details=true参数,接口会返回包含子结果列表的完整测试结果数据:
GET https://dev.azure.com/{organization}/{project}/_apis/test/Runs/{runId}/Results/{testCaseResultId}?details=true&api-version=6.0-preview.1
返回的JSON数据中,subResults数组里的每个对象都包含id字段,这个值就是你需要的testSubResultId。
随机数无效的原因
Azure DevOps的API会校验testSubResultId是否属于当前testCaseResultId对应的测试结果,随机生成的ID不存在于系统中,因此接口看似没有返回错误(可能返回204 No Content),但实际并未创建附件。程序终止大概率是因为后续逻辑依赖附件创建成功的状态,但未处理接口实际未生效的情况。
C#示例代码(获取TestSubResultId)
using System.Net.Http.Headers; using System.Text.Json; // 定义对应接口返回结构的实体类(仅保留必要字段) public class TestCaseResultDetails { public List<TestSubResult> SubResults { get; set; } = new(); } public class TestSubResult { public int Id { get; set; } // 目标TestSubResultId } // 调用接口获取子结果ID var pat = "你的个人访问令牌"; var org = "组织名"; var project = "项目名"; var runId = "测试运行ID"; var testCaseResultId = "测试用例结果ID"; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($":{pat}")) ); var requestUrl = $"https://dev.azure.com/{org}/{project}/_apis/test/Runs/{runId}/Results/{testCaseResultId}?details=true&api-version=6.0-preview.1"; var response = await client.GetAsync(requestUrl); response.EnsureSuccessStatusCode(); // 确保请求成功 var resultDetails = await response.Content.ReadFromJsonAsync<TestCaseResultDetails>(); // 根据实际需求取对应的子结果ID,比如第一个子结果 var targetSubResultId = resultDetails.SubResults.FirstOrDefault()?.Id; if (targetSubResultId == null) { // 处理无子结果的情况 throw new InvalidOperationException("当前测试用例结果不存在子结果"); }
注意事项
- 确保个人访问令牌(PAT)拥有Test Management -> Read & Write权限,否则无法查询测试结果详情或添加附件。
- 如果是自动化测试生成的子结果,需确认测试运行中确实存在对应的子结果,否则
subResults数组会为空。 - 请求体中的
Stream字段必须是文件内容的Base64编码,否则附件会无法正常打开。
内容的提问来源于stack exchange,提问作者SDHEER
相关产品推荐
相关产品推荐

