pythonazuretesting

Error associating test results in Azure DevOps API version 7.0 (works in version 5.0)


I am encountering an issue when trying to associate test results with a "test run" in Azure DevOps using the API version 7.0. The same code works perfectly with API version 5.0, but when I try to use version 7.0, I get the following error:

{
    "$id": "1",
    "innerException": null,
    "message": "TestPointId, testCaseId, testCaseRevision, testCaseTitle must be specified for planned test results.",
    "typeName": "Microsoft.TeamFoundation.TestManagement.WebApi.InvalidPropertyException, Microsoft.TeamFoundation.TestManagement.WebApi",
    "typeKey": "InvalidPropertyException",
    "errorCode": 0,
    "eventId": 3000
}

Here’s the code I’m using to associate the test results to the "test run":

async def associate_test_results(session, test_run_id, test_points):
    if not test_points:
        return

    headers = get_headers()
    url = f"https://dev.azure.com/{org_name}/{project_name}/_apis/test/runs/{test_run_id}/results?api-version=7.0"
    test_case_results = []

    results = parse_results_xml()  # Calls function that returns the test results

    for test in results:
        test_case_id = test.get('test_case_id')
        outcome = test.get('outcome', "Aborted")
        error_message = test.get('error_message')

        # Accessing elapsed time in seconds, and converting to milliseconds
        elapsed_seconds = test.get('elapsed_seconds', 0)
        elapsed_ms = elapsed_seconds * 1000

        test_point = next((point for point in test_points if point.get("testCase", {}).get("id") == test_case_id), None)

        if test_point:
            point_id = test_point.get("id")
            revision = test_point.get("testCase", {}).get("revision")
            title = test_point.get("testCase", {}).get("name", f"Test {test_case_id}")
            result = {
                "testPoint": {"id": point_id},
                "testCase": {"id": test_case_id},
                "testCaseRevision": revision,
                "testCaseTitle": title,
                "automatedTestName": f"TestClass.{test_case_id}",
                "automatedTestType": "RobotAutomation",
                "priority": 1,
                "outcome": outcome,
                "state": "Completed",
                "durationInMs": elapsed_ms,
                "actionResults": [
                    {
                        "actionPath": "000001",
                        "outcome": outcome,
                        "comment": f"Test result: {test_case_id}",
                    }
                ]
            }

            if outcome == "Failed" and error_message:
                result["errorMessage"] = error_message

            test_case_results.append(result)

    if test_case_results:
        try:
            async with session.post(url, headers=headers, json=test_case_results) as response:
                if response.status == 200:
                    log.info("Test results successfully associated.")
                    results = await response.json()  # Returns the created results
                    await upload_attachments_to_results(session, test_run_id, results)
                    return results
                else:
                    log.error(f"Error associating results: {response.status}, {await response.text()}")
        except aiohttp.ClientError as e:
            log.error(f"Error associating results: {e}")

Error: When using this code with API version 7.0, it returns a 400 Bad Request error with the following message: "TestPointId, testCaseId, testCaseRevision, testCaseTitle must be specified for planned test results."

Questions:

Documentation: https://learn.microsoft.com/en-us/rest/api/azure/devops/test/?view=azure-devops-rest-7.0 Endpoint: https://learn.microsoft.com/en-us/rest/api/azure/devops/test/results/add?view=azure-devops-rest-7.0&tabs=HTTP

Why does this error occur only with version 7.0 of the API and not 5.0? How can I resolve this issue and successfully associate the test results using version 7.0? I’ve tried verifying the parameters (testPointId, testCaseId, etc.), but it seems like everything is correctly passed. Any help or insights would be appreciated!


Solution

  • I am able to add the test results in test run using Rest API version 7.0

    I have used the below code to achieve it.

    async def associate_test_results(session, test_run_id, test_points):
    
        headers = get_headers()
        url = f"https://dev.azure.com/{org_name}/{project_name}/_apis/test/runs/{test_run_id}/results?api-version=7.0"
    
        results = parse_results_xml()  
        test_case_results = []
    
        for test in results:
            test_case_id = test.get("test_case_id")
            outcome = test.get("outcome", "Aborted")
            elapsed_ms = test.get("elapsed_seconds", 0) * 1000
            error_message = test.get("error_message", "")
    
            # Fetch corresponding test point
            test_point = next(
                (point for point in test_points if point.get("testCase", {}).get("id") == test_case_id), None
            )
    
            if test_point:
                point_id = test_point.get("id")
                revision = test_point.get("testCase", {}).get("revision", 1)
                title = test_point.get("testCase", {}).get("name", f"Test {test_case_id}")
    
                result = {
                    "testPoint": {"id": point_id},           
                    "testCase": {"id": test_case_id},        
                    "testCaseRevision": revision,            
                    "testCaseTitle": title,                  
                    "automatedTestName": f"TestClass.{test_case_id}",
                    "automatedTestType": "RobotAutomation",
                    "priority": 2,
                    "state": "Completed",
                    "outcome": outcome,
                    "durationInMs": elapsed_ms,
                    "actionResults": [
                        {
                            "actionPath": "000001",
                            "outcome": outcome,
                            "comment": f"Test result for {test_case_id}"
                        }
                    ]
                }
    
                if outcome == "Failed" and error_message:
                    result["errorMessage"] = error_message
    
                test_case_results.append(result)
            else:
                logging.warning(f'No matching test point found for TestCaseId: {test_case_id}')
    
        if test_case_results:
            try:
                async with session.post(url, headers=headers, json=test_case_results) as response:
                    if response.status == 200 or response.status == 201:
                        logging.info('Test results successfully fetched.')
                        created_results = await response.json()
                        return created_results
                    else:
                        error_text = await response.text()
                        logging.error(f'Failed to associate results: {response.status}, {error_text}')
            except aiohttp.ClientError as e:
                logging.error(f'Error while associating results: {str(e)}')
    
    async def main():
        async with aiohttp.ClientSession() as session:
            test_run_id = 2  
    
            test_points = [
                {
                    "id": "2",
                    "testCase": {
                        "id": "29423",
                        "name": "TestCase",
                        "revision": 1
                    }
                }
            ]
    
            results = await associate_test_results(session, test_run_id, test_points)
            if results:
                logging.info('Test results successfully associated.')
                print(results)
    

    Output :-

    enter image description here

    enter image description here