TFS 2018 API (4.1 version) – Python : Can’t add an attachment in a result of a run using either 4.1 or 5.1 version

Tags: , , , ,

I have managed to send my test results from my automation python script to TFS 2018 by creating a run and adding results to it.

Now, I am trying to upload the xml file I produce with the detailed results of the test execution using the Create Test Result Attachment API call . The version of our API is 4.1 and not 5.1 as far as I know.

This is the method I have written in order to achieve what I want:

def add_result_attachment(result_id, run_id, filename, stream, conf_object):    

    url = conf_object.config_map('TFS')['url'] + "TFS/_apis/test/Runs/" + str(run_id) + "/Results/" + str(result_id) + "/attachments"

    payload = "{n    "attachmentType": "GeneralAttachment",n    "fileName": "" + filename + "",n    "stream": "" + str(stream) + "",n    "comment": "Test"n}"

    # specify version of tfs and its rest api
    query_string = {"api-version": "5.1-preview"}

    headers = {
        'Content-Type': "application/json",
        'Authorization': MYKEY


    response = requests.request("POST", url, data=payload, headers=headers, params=query_string,  verify=False)

    print(str(response.status_code) + "n" + json.dumps(json.loads(response.text), indent=4) + 'n')

I have checked that the URL gives me the correct ids,so it is valid. filename contains the absolute path to the xml file i produce using my pytest command.

The stream contains the string of the base64 encoded form of this xml file.

When I execute this I get as a response:

Traceback (most recent call last):
  File "", line 210, in tearDown
    tfs_api.tfs_api.tfs_process(run_start_time, run_completed_time, class_name, method_name, steps, self.outcome)
  File "", line 263, in tfs_process
    tfs_api.send_run_results(run_start_time, run_completed_time, json_test_cases['id'], test_name, outcome)
  File "", line 586, in send_run_results
    tfs_api.add_result_attachment(result_id, run_id, filename, stream, conf_object)
  File "", line 457, in add_result_attachment
    print(str(response.status_code) + "n" + json.dumps(json.loads(response.text), indent=4) + 'n')
  File "", line 348, in loads
    return _default_decoder.decode(s)
  File "", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 2)

If I swap 5.1-preview to 4.1-preview for version I get status code 400 and the following response:

    "$id": "1",
    "innerException": null,
    "message": "Value cannot be null.rnParameter name: attachmentRequestModel",
    "typeName": "System.ArgumentNullException, mscorlib",
    "typeKey": "ArgumentNullException",
    "errorCode": 0,
    "eventId": 0

Is there a way to resolve the issue for the 4.1 version in case it is supported by this call or use somehow the 5.1 even if we don’t have the latest TFS ? I have tried also to send the attachment to the run itself instead of its result but no luck with that as well.

Any help would be appreciated. Thanks!


In case someone is still interested, someone has answered my question here.

Basically what needed change was to:

  • use a simpler path on the root of the project => TestsOut.log
  • convert the stream in a different way => stream = str(base64.b64encode(data), 'utf-8')

Source: stackoverflow