我正在将我们的一个项目转换为使用 Azure DevOps 而不是 AppVeyor 进行 CI。作为构建的一部分,我们使用自定义测试运行器来执行某些测试。
在 AppVeyor 中运行时,我们直接从测试运行程序调用 REST API,以通知构建服务器正在运行的测试并更新其状态。这非常简单,如其 REST 部分所示添加测试 https://www.appveyor.com/docs/build-worker-api/#add-tests and 更新测试 https://www.appveyor.com/docs/build-worker-api/#update-tests文档,并使我们能够很好地集成到 AppVeyor 的 UI 中。
我一直在研究如何在 Azure DevOps 中做同样的事情。我找到了 REST API 的一部分adding https://learn.microsoft.com/en-us/rest/api/azure/devops/test/results/add?view=azure-devops-rest-5.1 and updating https://learn.microsoft.com/en-us/rest/api/azure/devops/test/results/update?view=azure-devops-rest-5.1检测结果。从 API 文档中尚不完全清楚这是否是我在运行管道期间使用的,或者是否适用于其他场景。我已经搜索过其他人试图做同样的事情,但到目前为止没有任何运气。大多数示例都讨论上传测试结果文件,但这似乎是发布测试结果的一种相当间接的方式,特别是因为我想在运行之前注册所有测试,然后在完成时更新其状态。
有没有人有关于在构建期间使用 Azure DevOps API 发布测试结果的任何指示或示例?
详细解决方案:
在梅林梁的回答指导下,我现在已经开始工作了。
Step 1.首先,我创建了一个新的测试运行,这是我在构建作业结束时执行的(称为Build
)使用 powershell 脚本:
- powershell: |
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/test/runs?api-version=5.0"
$body = @{
"name" = "IntegrationTests"
"build" = @{
"id" = $env:BUILD_BUILDID
}
"isAutomated" = $TRUE
"state" = "InProgress"
}
$json = $body | ConvertTo-Json
$result = Invoke-RestMethod -Method 'Post' -Uri $url -Body $json -ContentType 'application/json' -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
$runId = $result.id
echo "##vso[task.setvariable variable=INTEGRATION_TEST_RUN_ID;isOutput=true]$runId"
displayName: 'Create test run'
name: CreateTestRun
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
请注意,您必须明确授予脚本访问权限System.AccessToken
in the env
部分,因为默认情况下该变量不会放入环境变量中。测试运行状态应该是InProgress
确保测试在运行时显示在构建的测试列表中。
Step 2.接下来,我的管道分散成并行作业来运行测试,这需要访问INTEGRATION_TEST_RUN_ID
我在上面创建的变量,因此我将其导入到作业中:
- job: IntegrationTests
dependsOn: Build
variables:
INTEGRATION_TEST_RUN_ID: $[ dependencies.Build.outputs['CreateTestRun.INTEGRATION_TEST_RUN_ID'] ]
strategy:
parallel: 2
...
然后我的测试运行程序(用 C# 编写)可以构造 URLPOST
ing and PATCH
荷兰国际集团测试:
$"{this.apiUrl}{this.projectName}/_apis/test/runs/{this.testRunId}/results?api-version=5.0"
并添加测试附件:
$"{this.apiUrl}{this.projectName}/_apis/test/runs/{this.testRunId}/results/{testResultId}/attachments?api-version=5.0-preview.1"
这些类成员变量只是从通常的环境变量中读取,并且testResultId
是我最初时API返回的IDPOST
考试。
再次,我明确设置SYSTEM_ACCESSTOKEN
in an env
当我从 Azure Pipeline YAML 调用测试运行程序并在授权标头中使用它时。
Step 3.最后,我再次在专用作业中将测试运行标记为完成,该作业取决于集成测试作业,并且即使测试失败也必须始终运行:
- job: EndIntegrationTests
dependsOn:
- Build
- IntegrationTests
condition: always()
variables:
INTEGRATION_TEST_RUN_ID: $[ dependencies.Build.outputs['CreateTestRun.INTEGRATION_TEST_RUN_ID'] ]
steps:
- checkout: none
- powershell: |
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/test/runs/$($env:INTEGRATION_TEST_RUN_ID)?api-version=5.0"
Write-Host "URL: $url"
$body = @{
"state" = "Completed"
}
$json = $body | ConvertTo-Json
Invoke-RestMethod -Method 'Patch' -Uri $url -Body $json -ContentType 'application/json' -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
displayName: 'Complete test run'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
请注意,这项工作需要明确依赖于Build
这样我就可以读取输出变量INTEGRATION_TEST_RUN_ID
,这显然取决于IntegrationTests
以便在所有测试完成之前它不会完成测试运行。