I’ve found a solution: VSTest uploads the test results (.trx) and coverage reports (.coverage) from each agent as test run attachments, but doesn’t say so in the logs.
To get all test run attachments, we first need the test run id. This isn’t the build id from the URL, but it can be retrieved using the $(Build.BuildUri) using this endpoint: https://vstmr.dev.azure.com/$org/$project/_apis/testresults/runs
With the test run id, we can query this endpoint to get all attachment filenames and download URLs: https://vstmr.dev.azure.com/$org/$project/_apis/testresults/runs/:runId/attachments
See the docs at
- Get test run id: Runs - List - REST API (Azure DevOps Test Results) | Microsoft Learn
- List attachments: Attachments - Get Test Run Attachments - REST API (Azure DevOps Test Results) | Microsoft Learn
$(System.AccessToken) can be used as a bearer token for authentication for these endpoints.
See Predefined variables - Azure Pipelines | Microsoft Learn for all available variables.
I created a script that downloads them all to $(Agent.TempDirectory)\TestResults and together with sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)\**\*.trx on SonarCloudPrepare everything is working as expected.