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!
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 :-