Avoiding Multiple Test Runs When Associating Test Results with Test Cases

Nataliia Melenivska 0 Reputation points
2025-03-11T09:39:01.0766667+00:00

I have a pipeline that runs integration tests, and I need to associate the test results with test cases in a test plan. To achieve this, I use scripts to:

  1. Update test cases within the test plan.
  2. Associate test results with the corresponding test cases.

While the process works and the results appear correctly in Azure, I noticed that an additional manual test run is created for each test case result association.

Is there a way to prevent these multiple test runs from being generated? Or is there an alternative approach to automatically associate test cases with test results after a test run without triggering new test runs?

Below are the scripts used for this process:

Script to automatically update test cases in Azure:

// Create a new test case

const createTestCase = async (testCase) => {

const url = `${config.orgUrl}/${config.project}/_apis/wit/workitems/$Test Case?api-version=6.0`;

const data = [

{ op: 'add', path: '/fields/System.Title', value: testCase.name },

{ op: 'add', path: '/fields/Microsoft.VSTS.TCM.AutomatedTestName', value: testCase.name },

{ op: 'add', path: '/fields/Microsoft.VSTS.TCM.AutomatedTestId', value: generateAutomatedTestId(testCase) }

];

try {

const response = await axios.post(url, data, { headers });

console.log(`Test case created: ${response.data.id}`);

return response.data.id;

} catch (error) {

console.error('Error creating test case:', error.response?.data || error.message);

throw error;

}

};

// Update an existing test case

const updateTestCase = async (testCaseId, testCase) => {

const url = `${config.orgUrl}/${config.project}/_apis/wit/workitems/${testCaseId}?api-version=6.0`;

const data = [

{ op: 'add', path: '/fields/System.Title', value: testCase.name },

{ op: 'add', path: '/fields/Microsoft.VSTS.TCM.AutomatedTestName', value: testCase.name }

];

try {

const response = await axios.patch(url, data, { headers });

console.log(`Test case updated: ${testCaseId}`);

return response.data.id;

} catch (error) {

console.error('Error updating test case:', error.response?.data || error.message);

throw error;

}

};

Script to associate Test cases with test results:

const associateTestResults = async (runId, testCaseId) => {

const url = `${config.orgUrl}/${config.project}/_apis/test/runs/${runId}/results?api-version=6.0`;

const body = [{

testCase: { id: testCaseId },

outcome: "Passed"

}];

try {

const response = await axios.post(url, body, { headers });

console.log(`Test result associated with test case ${testCaseId}`);

} catch (error) {

console.error('Error associating test result:', error.response?.data || error.message);

throw error;

}

};

YAML Tasks to execute these steps:

- script: |
          npm run test || exit 0
        displayName: 'Run tests'
        env:
          TEST_USER_PASSWORD: $(TEST_USER_PASSWORD)
          SERVICE_BUS_CONNECTION_STRING: $(SERVICE_BUS_CONNECTION_STRING)

      - task: PublishTestResults@2
        inputs:
          testResultsFormat: 'JUnit'
          testResultsFiles: '**/results/testResults.xml'
          testRunTitle: 'IntegrationTests-TEST'
          publishRunAttachments: true
        displayName: 'Publish Test Results'
        name: PublishTestResults

      - task: PowerShell@2
        displayName: 'Get Latest Test Run ID'
        inputs:
          targetType: 'inline'
          script: |
            $url = "https://org/project/_apis/test/runs?api-version=7.1-preview.3"
            $headers = @{
              "Authorization" = "Bearer $(AZURE_DEVOPS_API_TOKEN)"
              "Content-Type" = "application/json"
            }

            $maxRetries = 10
            $retryDelay = 5  
            $testRunId = $null

            for ($i = 1; $i -le $maxRetries; $i++) {
                Write-Host "Attempt $($i): Fetching test run..."
                try {
                    $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
                    Write-Host "Response: $($response | ConvertTo-Json)"
                    
                    $matchingRun = $response.value | Where-Object { $_.name -eq "IntegrationTests-TEST" } | Sort-Object -Property id -Descending | Select-Object -First 1

                    if ($matchingRun) {
                        $testRunId = $matchingRun.id
                        Write-Host "Found Test Run ID: $testRunId"
                        break
                    }
                } catch {
                    Write-Host "Error: $($_.Exception.Message)"
                }

                Write-Host "Test Run ID not found yet. Retrying in $retryDelay seconds..."
                Start-Sleep -Seconds $retryDelay
            }

            if (-not $testRunId) {
                Write-Host "##[error]Failed to retrieve Test Run ID after $maxRetries attempts."
                exit 1
            }

            Write-Host "##vso[task.setvariable variable=TEST_RUN_ID]$testRunId"
        env:
          AZURE_DEVOPS_API_TOKEN: $(AZURE_DEVOPS_API_TOKEN)

      - script: |
          node $(System.DefaultWorkingDirectory)/results/testResults.js
        displayName: 'Process Test Results'
        env:
          TEST_RUN_ID: $(TEST_RUN_ID)
          AZURE_DEVOPS_API_TOKEN: $(AZURE_DEVOPS_API_TOKEN)

Azure DevOps
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. RithwikBojja 790 Reputation points Microsoft External Staff
    2025-03-12T07:11:17.4733333+00:00

    Hi @Nataliia Melenivska,

    Since you’re manually associating test results using the API, Azure DevOps might be generating additional test runs instead of updating the existing one.

    To resolve the issue ,

    • ⁠Associate test results directly within the test run by ensuring test cases have the correct Automated Test ID and Test Case Links in the test plan. When using PublishTestResults@2, Azure DevOps will automatically link results to the test cases. No separate API request is needed.
    • Use the built-in TestResults@2 task instead of custom API calls to associate test results with test runs,
      
          - task: TestResults@2  
      
          inputs:  
      
          testResultsFormat: 'VSTest'  
      
          testResultsFiles: '**/results/testResults.xml'  
      
          searchFolder: '$(System.DefaultWorkingDirectory)'  
      
          mergeTestResults: true  
      
          failTaskOnFailedTests: true  
      
          testRunTitle: 'IntegrationTests-TEST'  
      
          
      
      
      This avoids unnecessary API calls and links results to existing test runs automatically.
    • Update your API call to PATCH the existing test run instead of creating a new one,
      
          const url = `${config.orgUrl}/${config.project}/_apis/test/runs/${runId}?api-version=6.0`;  
      
          await axios.patch(url, { state: "Completed" }, { headers }); ```
      
      

    This updates the test run instead of creating a new one.

    • As you’re using api-version=6.0, but newer versions (e.g., 7.1-preview.3) provide better control over test result association. Try updating the API version in your REST API calls.

    Hope this helps.

    If the answer is helpful, please click Accept Answer and kindly upvote it. If you have any further questions about this answer, please click Comment.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.