Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add Attachment to Test Steps? #155

Closed
jfthuong opened this issue Jan 3, 2019 · 9 comments
Closed

How to add Attachment to Test Steps? #155

jfthuong opened this issue Jan 3, 2019 · 9 comments
Labels

Comments

@jfthuong
Copy link

jfthuong commented Jan 3, 2019

I would like to add attachments to some of the steps of my Test Cases like I can do in the Web Interface.

This is how I want my step to look like:

Step with attachment

... and when you run it, that would look like this:
enter image description here

However, I have not been able to find where this information is stored.

This is the JSON data for the WorkItem of my Test Case

{
id: 224,
rev: 2,
fields: {
    System.AreaPath: "GM_sandbox\GM-Toto",
    System.TeamProject: "GM_sandbox",
    System.IterationPath: "GM_sandbox",
    System.WorkItemType: "Test Case",
    System.State: "Design",
    System.Reason: "New",
    System.AssignedTo: "Jeff",
    System.CreatedDate: "2019-01-03T01:43:09.743Z",
    System.CreatedBy: "Jeff",
    System.ChangedDate: "2019-01-03T02:12:07.15Z",
    System.ChangedBy: "Jeff",
    System.Title: "Titi",
    Microsoft.VSTS.Common.StateChangeDate: "2019-01-03T01:43:09.743Z",
    Microsoft.VSTS.Common.ActivatedDate: "2019-01-03T01:43:09.743Z",
    Microsoft.VSTS.Common.ActivatedBy: "Jeff",
    Microsoft.VSTS.Common.Priority: 2,
    Microsoft.VSTS.TCM.AutomationStatus: "Not Automated",
    Microsoft.VSTS.TCM.Steps: "<steps id="0" last="2"><step id="2" type="ValidateStep"><parameterizedString isformatted="true">&lt;DIV&gt;&lt;P&gt;Click on the rainbow button&lt;/P&gt;&lt;/DIV&gt;</parameterizedString><parameterizedString isformatted="true">&lt;P&gt;Screen becomes Blue (see picture)&lt;/P&gt;</parameterizedString><description/></step></steps>"
},
_links: {
    self: {
        href: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/workItems/224"
    },
    workItemUpdates: {
        href: "https://my_server.com:8443/tfs/PRODUCT/_apis/wit/workItems/224/updates"
    },
    workItemRevisions: {
        href: "https://my_server.com:8443/tfs/PRODUCT/_apis/wit/workItems/224/revisions"
    },
    workItemHistory: {
        href: "https://my_server.com:8443/tfs/PRODUCT/_apis/wit/workItems/224/history"
    },
    html: {
        href: "https://my_server.com:8443/tfs/PRODUCTi.aspx?pcguid=4107d6a2-eaaa-40b9-9a8d-f8fdbb31d4b7&id=224"
    },
    workItemType: {
        href: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/workItemTypes/Test%20Case"
    },
    fields: {
        href: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/fields"
    }
},
url: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/workItems/224"
}

Any idea on where this information is stored?

And, if possible, could anyone tell me how to add an attachment from a file and link it to the test step?

Thanks a lot

@jfthuong jfthuong changed the title [Q] How to add Attachment to Test Steps? How to add Attachment to Test Steps? Jan 4, 2019
@tedchamb
Copy link
Member

tedchamb commented Jan 4, 2019

Seleha from the TCM team has provided us with this helpful information:

This will be a two step process

  1. The first step is to add an attachment to the test case work item.
    This can be done using this API - https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/attachments/create?view=azure-devops-rest-5.0
  2. To attach the uploaded attachment to the test step, you can use this API sample - https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/update?view=azure-devops-rest-5.0#add_an_attachment with comment as [TestStep=] and URL as obtained from the previous API.
    If however you are open to using C# or JS clients, this step is simplified. The samples can be found here - https://blogs.msdn.microsoft.com/devops/2016/11/02/how-to-use-test-step-using-rest-client-helper/

Regards
Saleha

In the python code the methods for step 1 and 2 can be found here:

  1. WorkItemTrackingClient create_attachment
  2. WorkItemTrackingClient update_work_item

I hope this helps,
Ted

@jfthuong
Copy link
Author

jfthuong commented Jan 7, 2019

Thank you for the answer, that will help a bit to understand.

Could you tell me actually what is the stream for the create_attachment function?

    def create_attachment(self, upload_stream, project=None, file_name=None, upload_type=None, area_path=None):
        """CreateAttachment.
        Uploads an attachment.
        :param object upload_stream: Stream to upload
        ...
        """

I tried both solutions below but none seems to work:

with open('./smiley.png', "rb") as f:
    binary_content = bytes(f.read())
attachment = client_wit.create_attachment(binary_content, project, 'smiley.png')
attachment = client_wit.create_attachment("Hello my friend", project, 'test6.txt')

(this solution creates a text file but it contains the double quotes in the text)

Thanks

@tedchamb
Copy link
Member

tedchamb commented Jan 8, 2019

@jfthuong , sorry about that. There is currently a bug blocking uploads, that is being tracked is being tracked by #129. Hope to get this resolved soon.

@jfthuong
Copy link
Author

jfthuong commented Jan 9, 2019

I see.

Hope it will be resolved soon.

The only step I miss is that one (uploading a file correctly).

This the code I have used for attaching an uploaded attachment to a Test Step
NOTE: You need to have both the attribute name and the comment [TestStep=x]: when you update the Test Case otherwise it is not linked to Test Step.

def add_attachment(wit_id: int, project: str, url:str, comment: str, name:str = None):
    """Add attachment already uploaded to a WorkItem"""
    # We want to have the possibility to set a comment
    attributes = {"comment": comment}
    if name is not None:
        attributes["name"] = name

    patch_document = [
        JsonPatchOperation(
            op="add",
            path="/relations/-",
            value={
                "rel": "AttachedFile",
                "url": url,
                "attributes": attributes,
            },
        )
    ]
    return wit_client.update_work_item(patch_document, wit_id, project)

def add_attachment_to_step(tc_id:int, project:str, url:str, step:int, comment="", name=""):
    """Add an attachment to a given step of a Test Case"""
    name = name if name else re.sub(r".*fileName=", "", url)
    comment = f"[TestStep={step}]:{comment}"
    return add_attachment(tc_id, project, url, comment, name)

attachment = client.wit.create_attachment(my_stream, project, 'my_picture.png')
add_attachment_to_step(my_tc, project, attachment.url, 3, "Expected result")

I will close the issue and hope #129 to be solved very soon.

Thanks again for the support

@jfthuong jfthuong closed this as completed Jan 9, 2019
@tedchamb
Copy link
Member

@jfthuong The fix has been released in 0.1.24

Example method to upload a file and link it as a work item attachment:

def upload_work_item_attachment(wit_client, work_item_id, file_name, callback=None):
    # upload file / create attachment
    with open(file_name, 'r+b') as file:
        # use mmap, so we don't load entire file in memory at the same time, and so we can start
        # streaming before we are done reading the file.
        mm = mmap.mmap(file.fileno(), 0)
        attachment = wit_client.create_attachment(mm, file_name=file_name, callback=callback)

    # Link Work Item to attachment
    patch_document = [
        JsonPatchOperation(
            op="add",
            path="/relations/-",
            value={
                "rel": "AttachedFile",
                "url": attachment.url
            }
        )
    ]
    wit_client.update_work_item(patch_document, work_item_id)

@jfthuong
Copy link
Author

Awesome!!!

@bbalfour5
Copy link

The example method seems to be working for me, except I get the error JsonPatchOperation is not defined. Is there a library or extension I need to use for it?

@ym500
Copy link

ym500 commented Oct 7, 2021

hi @bbalfour5 , just come to it now
you need to import it with

from azure.devops.v5_1.py_pi_api import JsonPatchOperation

@jfthuong
Copy link
Author

jfthuong commented Oct 9, 2021

Actually I was importing it like from azure.devops.v5_1.work_item_tracking.models

from azure.devops.v5_1.work_item_tracking.models import JsonPatchOperation

Or if you use version 4.1 of the API:

from vsts.work_item_tracking.v4_1.models.json_patch_operation import JsonPatchOperation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants