def test_epic_update():
    """
        Using a known valid Rally server and known valid access credentials,
        exercise the Rally.create method to create an Epic instance and be handed
        back a usable pyral.entity representing the newly created Epic PortfoloItem instance.
        Then a few seconds later, query for that newly created Epic and update a couple
        of the attributes of the Epic (Name, Ready) and receive back an instance of the updated Epic
        that is non-None and can be interrogated for all atribute information.
    """
    rally = Rally(server=RALLY, apikey=APIKEY)
    rally.setWorkspace('NMTest')
    target_workspace = rally.getWorkspace()

    rally.setProject('*MFA Benefit Durt')
    target_project = rally.getProject()

    epic_info = {
        "Workspace":
        target_workspace._ref,
        "Project":
        target_project._ref,
        "Name":
        "Funicular Wax Shine-athon",
        "Description":
        "Guests hands must not stick on the gate handle and must slide off the viewing port without leaving a dirty handprint",
        #"Ready"       : False,
        #"Parent"      : don't need a Feature ref for this test
    }

    print("Creating Funicular Epic ...")
    epic = rally.create('PortfolioItem/Epic', epic_info)
    assert epic
    print("Created Epic item {0}".format(epic.FormattedID))
    assert epic.Name == "Funicular Wax Shine-athon"
    assert epic.Ready == False
    time.sleep(3)

    print("Updating Funicular Epic {0}...".format(epic.FormattedID))
    upd_info = {
        'FormattedID': epic.FormattedID,
        'Name': "Funicular haz beenz shinola-ed",
        'Ready': True
    }
    upd_epic = rally.update('PortfolioItem/Epic', upd_info)
    assert upd_epic
    assert upd_epic.Name == "Funicular haz beenz shinola-ed"
    assert upd_epic.Ready == True
    print("PortfolioItem/Epic update was successful")

    time.sleep(2)
    result = rally.delete('PortfolioItem/Epic', upd_epic.FormattedID)
    assert result == True
    print("PortfolioItem/Epic crash-test-dummy {0} has been deleted".format(
        epic.FormattedID))
def test_delete_pull_request():
    #rally = Rally(server=TESTN, user=TESTN_USER, password=TESTN_PSWD)
    rally = Rally(server=AGICEN, apikey=AGICEN_SUB_100_API_KEY)
    attrs = "ExternalId,ExternalFormattedId,Artifact,Name,Url,Description"
    response = rally.get('PullRequest', fetch=attrs, project=None)
    assert response.status_code == 200
    assert len(response.errors) == 0
    assert len(response.warnings) == 0
    prs = [pr for pr in response]
    assert len(prs) > 0
    victim = prs[0]
    result = rally.delete('PullRequest', victim.oid, project=None)
    assert result == True

    response = rally.get('PullRequest', fetch=attrs, query='ObjectID = %s' % victim.oid)
    ghosts = [pr for pr in response]
    assert not ghosts
Exemple #3
0
def test_add_tcr_attachment():
    """
        Add an Attachment to a TestCaseResult item

        Create a TestCase, save a reference
        Create a TestCaseResult to be associated with the TestCase
        Create an attachment
        Attach the Attachment to the TestCaseResult item
    """
    #rally = Rally(server=RALLY, user=RALLY_USER, password=RALLY_PSWD)
    rally = Rally(server=RALLY,
                  user=RALLY_USER,
                  apikey=APIKEY,
                  workspace=DEFAULT_WORKSPACE,
                  project=DEFAULT_PROJECT)
    wksp = rally.getWorkspace()
    assert wksp.Name == DEFAULT_WORKSPACE

    response = rally.get('Project', fetch=False, limit=10)
    assert response != None
    assert response.status_code == 200
    proj = rally.getProject()  # proj.Name == Sample Project
    assert proj.Name == 'Sample Project'

    tc_info = {
        "Workspace": wksp.ref,
        "Project": proj.ref,
        "Name": "Heat exposure",
        "Type": "Functional",
    }
    test_case = rally.create('TestCase', tc_info)
    assert int(test_case.oid) > 0

    current = timestamp()[:-4].replace(' ', 'T') + "Z"

    tcr_info = {
        "Workspace": wksp.ref,
        "TestCase": test_case.ref,
        "Date": current,
        "Build": 27,
        "Verdict": "Pass"
    }
    tcr = rally.create('TestCaseResult', tcr_info)
    assert int(tcr.oid) > 0

    attachment_name = "Addendum.txt"
    att_ok = conjureUpAttachmentFile(attachment_name)
    assert att_ok == True

    att = rally.addAttachment(tcr, attachment_name)
    assert att.Name == attachment_name
    target = ['Build = 27', f'TestCase = {test_case.ref}']
    response = rally.get("TestCaseResult",
                         fetch='ObjectID,FormattedID,Attachments',
                         query=target,
                         project=None)
    assert response.resultCount == 1
    tcr = response.next()
    attachment = rally.getAttachment(tcr, attachment_name)
    assert attachment.Name == attachment_name
    att_type = attachment.ContentType
    assert att_type == 'text/plain'
    att = tcr.Attachments[0]
    actual_attachment_content = attachment.Content.decode('UTF-8').replace(
        "\r", '')
    att_content = att.Content.decode('UTF-8').replace("\r", '')

    assert actual_attachment_content == EXAMPLE_ATTACHMENT_CONTENT
    assert att_content == EXAMPLE_ATTACHMENT_CONTENT
    #assert attachment.Content.decode('UTF-8') == EXAMPLE_ATTACHMENT_CONTENT
    #assert att.Content.decode('UTF-8')        == EXAMPLE_ATTACHMENT_CONTENT
    rally.deleteAttachment(tcr, attachment_name)
    rally.delete('TestCaseResult', tcr)
    rally.delete('TestCase', test_case)
Exemple #4
0
class RallyUtil(object):
    def __init__(self, RallyServer='rally1.rallydev.com', \
                 APIKep='_fONhEFO2RHW87EMPIc4II1yY1fx4PEmtgpW85jMq7eI', \
                 workspace='MicroStrategy Workspace', project='SR-Intelligence-Kernel', \
                 loggingfile='Rally.log'):
        self.rally = Rally(server=RallyServer,
                           apikey=APIKep,
                           workspace=workspace,
                           project=project,
                           projectScopeDown=True)
        self.rally.enableLogging(loggingfile)

    def get_testcase_by_id(self, testcase_id):
        return self._get_entity_by_id(testcase_id)

    def get_testset_by_id(self, testset_id):
        return self._get_entity_by_id(testset_id)

    def set_testcase_name(self, testcase_id, testcase_name):
        self._set_entity(testcase_id, Name=testcase_name)

    def _get_entity_by_id(self, entity_id):
        entity_type = self._get_entity_type(entity_id)
        query = 'FormattedID = {}'.format(entity_id)
        return self.rally.get(entity_type,
                              query=query,
                              project=None,
                              instance=True)

    def get_defect_by_id(self, defect_id):
        return self._get_entity_by_id(defect_id)

    def _set_entity(self, entity_id, **info):
        entity_type = self._get_entity_type(entity_id)
        info['FormattedID'] = entity_id
        logger.debug(info)
        self.rally.update(entity_type, info)

    def get_object_by_id(self, type, oid):
        response = self.rally.get(type,
                                  fetch=True,
                                  query='ObjectID = ',
                                  workspace=workspace,
                                  project=project)

    def get_alluserinfo(self):
        return self.rally.getAllUsers()

    def get_userstorys_by_product_release(self, *product_releases):

        query = 'c_ProductionRelease = "11.1.2 [2019-Jun-7]" OR c_ProductionRelease = "11.2 RC [2019-Sep-20]" OR c_ProductionRelease = "11.2 EA [2019-Jun-21]"'
        # query = 'c_ProductionRelease = "11.1.2 [2019-Jun-7]"'
        response = self.rally.get('UserStory',
                                  query=query,
                                  fetch=True,
                                  projectScopeDown=True)

        userstorys = []
        for entry in response:
            logger.debug(entry.FormattedID, entry.Name)
            userstorys.append(entry)

        return userstorys

    def create_testcase(self, testcase_name, testfolder_id, status, test_type,
                        owner):
        # note, owner should be Email address, e.g. [email protected]

        testcase_json = {
            "Workspace": self.rally.getWorkspace().ref,
            "Project": self.rally.getProject().ref,
            "Name": testcase_name,
            "TestFolder": self.get_testfolder(testfolder_id)._ref,
            "Method": "Manual",
            "Type": test_type,
            "Priority": "Useful",
            "Risk": "Low",
            "c_TestCaseStatus": status,
            "c_UPCComponent": "017 Tool : Administration",
            "c_UPCModule": "017.000 Administration",
            "Owner": self.rally.getUserInfo(username=owner)[0].ref
        }
        testcase = self.rally.create('TestCase', testcase_json)
        logger.debug(testcase.details())
        return testcase

    def create_testset(self, testsetName, iterationName, stage, test_type,
                       owner):
        # note, owner should be Email address, e.g. [email protected]

        query = 'Name = "%s"' % iterationName
        iteration = self.rally.get('Iteration',
                                   fetch=True,
                                   query=query,
                                   projectScopeDown=True)
        # workspace=workspace, project=project)
        iteration = next(iteration, None)
        if not iteration:
            logging.error(f"{create_testset.__name__} get iteration fail")
            return

        testset_json = {
            "Workspace": self.rally.getWorkspace().ref,
            "Project": self.rally.getProject().ref,
            "Name": testsetName,
            "c_Result": "Unexecuted",
            "c_Stage": stage,
            "c_Type": test_type,
            "Iteration": iteration.ref,
            # "c_UPCComponent": "017 Tool : Administration",
            # "c_UPCModule": "017.000 Administration",
            "Owner": self.rally.getUserInfo(name=owner)[0].ref
        }
        testset = self.rally.create('TestSet', testset_json)
        logger.debug(testset.details())
        return testset.FormattedID

    def create_testcaseFromDefect(self, defect, owner=None, **testcase_json):
        # note, owner should be corp user name, such as "Jine Wang"
        # ident_query = 'FormattedID = "%s"' % defectID
        # workproduct = self.rally.get('Defect', fetch=True, query=ident_query, projectScopeDown=True)
        # # workproduct = self.rally.get('Defect', fetch=True, query=ident_query, workspace='current', project='current')
        # # self.rally.get.get(entity_name, fetch=True, query=ident_query, workspace=workspace, project=project)
        # defect = workproduct.next()

        testcase_json["Workspace"] = self.rally.getWorkspace().ref
        testcase_json["Project"] = self.rally.getProject().ref
        testcase_json[
            "Name"] = defect.FormattedID + " | " + defect.c_ProductionRelease.split(
            )[0] + " | " + defect.Name
        testcase_json["Description"] = defect.Description
        testcase_json["Owner"] = defect.Owner._ref
        testcase_json["WorkProduct"] = defect._ref
        testcase_json["Risk"] = "Low"
        testcase_json["c_UPCModule"] = defect.c_UPCModule
        testcase_json["c_UPCComponent"] = defect.c_UPCComponent
        testcase_json["c_TestCaseStatus"] = "Active"
        testcase_json["Type"] = "Regression"

        testcase = self.rally.create('TestCase', testcase_json)
        print(testcase.FormattedID, defect.FormattedID)
        return testcase

    def gettestcasesFromDefect(self, defect):
        result = []
        testcases = self.rally.getCollection(
            "https://rally1.rallydev.com/slm/webservice/v2.0/Defect/" +
            str(defect.oid) + "/TestCases")
        if testcases.errors:
            logging.error(f"{defect.FormattedID} Error in getting test cases")
        else:
            flag = True
            for testcase in testcases:
                flag = False
                result.append(testcase.FormattedID)
                logging.info(
                    f'{defect.FormattedID} {testcase.FormattedID} {testcase.c_TestCaseStatus} {testcase.Method}'
                )
        if flag:
            logging.info(f'         {defect.FormattedID} has no test case')
        return result

    def get_testcases_from_testfolder(self, testfolder_id):
        # query critial to get all active test cases
        query = 'TestFolder.FormattedID = "%s"' % testfolder_id
        response = self.rally.get('TestCase',
                                  query=query,
                                  fetch=True,
                                  projectScopeDown=True)

        test_cases = []
        for entry in response:
            logger.debug(entry.FormattedID, entry.Name)
            test_cases.append(entry)

        return test_cases

    def get_testcases_from_testset(self, testset_id):
        # query critial to get all active test cases
        query = 'TestSet.FormattedID = "%s"' % testset_id
        response = self.rally.get('TestCase',
                                  query=query,
                                  fetch=True,
                                  projectScopeDown=True)
        # get('TestSet', fetch=True, query='FormattedID = "%s"' % ts)
        test_cases = []
        for entry in response:
            logger.debug(entry.FormattedID, entry.Name)
            test_cases.append(entry)

        return test_cases

    def delete_all_testcases_in_testfolder(self, testfolder_id):
        for item in self.get_testcases_from_testfolder(
                testfolder_id=testfolder_id):
            logger.info('deleting testcase {} {}'.format(
                item.FormattedID, item.Name))
            self.rally.delete(entityName='TestCase',
                              itemIdent=item.FormattedID,
                              project='current',
                              workspace='current')

    def get_defects_by_date(self, defect_id, start_date, end_date):
        query = 'Iteration.StartDate > "{}" AND Iteration.StartDate < "{}"'.format(
            start_date, end_date)
        response = self.rally.get('Defect',
                                  fetch=True,
                                  query=query,
                                  projectScopeDown=True)
        defects = []
        for item in response:
            logger.debug('{},{}'.format(item.FormattedID, item.Name))
            defects.append(item)

    def get_defects_with_query(self, query):
        response = self.rally.get('Defect',
                                  fetch=True,
                                  query=query,
                                  projectScopeDown=True)
        defects = []
        for item in response:
            logger.debug('{},{}'.format(item.FormattedID, item.Name))
            defects.append(item)

        return defects

    def set_defect(self, defect_id, **info):
        self._set_entity(defect_id, **info)

    def add_testresult(self, testcase_id, **info):
        # logger.info('adding test result to {}'.format(testcase_id))
        info['TestCase'] = self.get_testcase_by_id(testcase_id).ref
        if not 'date' in info:
            info['date'] = str(datetime.datetime.utcnow().isoformat())
        if not 'tester' in info:
            info['tester'] = self.get_testcase_by_id(testcase_id).Owner.ref
        if not 'Verdict' in info:
            info['Verdict'] = 'Unexecuted'
        if not 'c_ProductionRelease' in info:
            info['c_ProductionRelease'] = '11.1.2 [2019-Jun-7]'
        if not 'Build' in info:
            info['Build'] = '0.0.0.0'
        if not 'Notes' in info:
            info['Notes'] = 'this result was added by script automatically'

        # self.rally.create('TestCaseResult', info)
        try:
            self.rally.create('TestCaseResult', info)
            logger.info('test case result for test case {} is added'.format(
                testcase_id))
        except Exception as re:
            logger.error('Fail to update test case {}, {}'.format(
                testcase_id, re))

    def add_testcasetotestset(self, testset_id, testcase_id):
        entity = self._get_entity_by_id(testset_id)
        testcasesList = []
        testcase = self.get_testcase_by_id(testcase_id)
        testcasesList.append(testcase)

        try:
            self.rally.addCollectionItems(entity, testcasesList)
            logger.info('adding test case {} to test set {}'.format(
                testcase.FormattedID, testset_id))
        except Exception as re:
            logger.error('Fail to add test case {} to test set {}: {}'.format(
                testcase_id, testset_id, re))

    def add_testcasetotestfolder(self, testfolder_id, testcase_id):
        entity = self._get_entity_by_id(testfolder_id)
        testcasesList = []
        testcase = self.get_testcase_by_id(testcase_id)
        testcasesList.append(testcase)

        try:
            self.rally.addCollectionItems(entity, testcasesList)
            logger.info('adding test case {} to test set {}'.format(
                testcase.FormattedID, testfolder_id))
        except Exception as re:
            logger.error('Fail to add test case {} to test set {}: {}'.format(
                testcase_id, testfolder_id, re))

    def add_defectstouserstory(self, userstory_id, defect_id):
        entity = self._get_entity_by_id(userstory_id)
        testcasesList = []
        defect = self.get_testcase_by_id(defect_id)
        testcasesList.append(defect)

        try:
            self.rally.addCollectionItems(entity, testcasesList)
            logger.info('adding test case {} to test set {}'.format(
                defect_id.FormattedID, userstory_id))
        except Exception as re:
            logger.error('Fail to add test case {} to test set {}: {}'.format(
                defect_id, userstory_id, re))

    def copyTestSet(self, sourcetestset_id, c_ProductionRelease, c_Stage):
        entity = self._get_entity_by_id(sourcetestset_id)
        # ident_query = 'FormattedID = "%s"' % sourcetestset_id
        # testset = self.rally.get('TestSet', fetch=True, query=ident_query, instance=True)
        # testset = testset.next()

        # querytestcase = 'TestCase.FormattedID = "%s"' % testcase_id
        # testcaseDiscussion = self.rally.get('ConversationPost', query=querytestcase, instance=True)

        # info = {}
        # info['c_ProductionRelease'] = c_ProductionRelease
        # info['Tasks'] = entity.Tasks
        # info['Owner'] = entity.Owner
        # info['Description'] = entity.Description
        # info['Name'] = entity.Name
        # info['Project'] = entity.Project
        # info['TestCases'] = entity.TestCases
        # info['c_Stage'] = c_Stage

        # testset_json = {
        #     "Workspace" : self.rally.getWorkspace().ref,
        #     "Project" : self.rally.getProject().ref,
        #     "Name" : entity.Name,
        #     "Description" : entity.Description,
        #     "c_ProductionRelease" : c_ProductionRelease,
        #     "Tasks" : entity.Tasks['_ref'],
        #     "Owner" : entity.Owner['_ref'],
        #     "TestCases" : entity.TestCases['_ref'],
        #     "c_Stage" : c_Stage,
        #     # "c_UPCComponent" : "017 Tool : Administration",
        #     # "c_UPCModule" : "017.000 Administration",
        #     # "Owner" : self.rally.getUserInfo(username=owner)[0].ref
        # }

        # taskList = testset.__collection_ref_for_Tasks
        # testset.__getattr__(__collection_ref_for_Tasks)

        testset_json = {
            "Workspace": self.rally.getWorkspace().ref,
            "Project": self.rally.getProject().ref,
            "Name": entity.Name,
            "Description": entity.Description,
            "c_ProductionRelease": c_ProductionRelease,
            # "Tasks" : testset.__collection_ref_for_Tasks,
            # "Owner" : testset.Owner['_ref'],
            # "TestCases" : __collection_ref_for_TestCases,
            "c_Stage": c_Stage,
            # "c_UPCComponent" : "017 Tool : Administration",
            # "c_UPCModule" : "017.000 Administration",
            # "Owner" : self.rally.getUserInfo(username=owner)[0].ref
        }
        testset = self.rally.create('TestSet', testset_json)
        logger.info('create test set {}'.format(testset.FormattedID))

        ident_query = 'TestSet.FormattedID = "%s"' % sourcetestset_id
        testcaseResponse = self.rally.get('TestCase',
                                          fetch=True,
                                          query=ident_query,
                                          instance=True)

        # testcaseList = []
        for testcase in testcaseResponse:
            testcaseList = []
            testcaseList.append(testcase)
            try:
                responses = self.rally.addCollectionItems(
                    testset, testcaseList)
                logger.info('adding test case {} to test set {}'.format(
                    testcase.FormattedID, testset.FormattedID))
            except Exception as re:
                logger.error(
                    'Fail to add test case {} to test set {}: {}, {}'.format(
                        testcase.FormattedID, testset.FormattedID, re,
                        responses.errors))

        # ident_querytask = 'TestSet.FormattedID = "%s"' % sourcetestset_id
        # taskResponse = self.rally.get('Task', fetch=True, query=ident_querytask, instance=True)

        taskList = entity.Tasks
        responses = self.rally.addCollectionItems(testset, taskList)

        # for task in taskResponse :
        #     taskList = []
        #     taskList.append(task)
        #     try :
        #         responses = self.rally.addCollectionItems(testset, taskList)
        #         logger.info('adding test case {} to test set {}'.format(task.FormattedID, testset.FormattedID))
        #     except Exception as re :
        #         logger.error(
        #             'Fail to add test case {} to test set {}: {}, {}'.format(task.FormattedID, testset.FormattedID,
        #                                                                      re, responses.errors))

        print(testcase)
        logger.debug(testcase.details())
        # print(info)
        # ident_query = 'TestSet.FormattedID = "%s"' % sourcetestset_id

        # testcaseResponse = rallyUtil.rally.get('TestCase', fetch=True, query=ident_query, project='current', workspace='current')
        #
        # testcaseList = []
        # for testcase in testcaseResponse:
        #     testcaseList.append(testcase)
        #     try :
        #         self.rally.addCollectionItems(entity, testcasesList)
        #         logger.info('adding test case {} to test set {}'.format(testcase.FormattedID, testset_id))
        #     except Exception as re :
        #         logger.error('Fail to add test case {} to test set {}: {}'.format(testcase_id, testset_id, re))

    def remove_testcasesfromtestset(self, testset_id, testcase_id):
        # querytestcase = 'TestCase.FormattedID = "%s"' % testcase_id
        # testcase = self.rally.get('TestCase', query=querytestcase, instance=True)
        #
        #
        # testcasesList = []
        # testcasesList.append(testcase.next())
        # self.rally.dropCollectionItems(self._get_entity_by_id(testset_id), testcasesList)
        # logger.info('remove testcase {} from testset {}'.format(testcase.FormattedID, testset_id))
        entity = self._get_entity_by_id(testset_id)
        testcasesList = []
        testcase = self.get_testcase_by_id(testcase_id)
        testcasesList.append(testcase)

        try:
            self.rally.dropCollectionItems(entity, testcasesList)
            logger.info('remove testcase {} from testset {}'.format(
                testcase.FormattedID, testset_id))
        except Exception as re:
            logger.error(
                'Fail to remove test case {} from test set {}: {}'.format(
                    testcase.FormattedID, re))

    def remove_testset(self, testset_id, osList):
        # querytestcase = 'TestCase.FormattedID = "%s"' % testcase_id
        # testcase = self.rally.get('TestCase', query=querytestcase, instance=True)
        #
        #
        # testcasesList = []
        # testcasesList.append(testcase.next())
        # self.rally.dropCollectionItems(self._get_entity_by_id(testset_id), testcasesList)
        # logger.info('remove testcase {} from testset {}'.format(testcase.FormattedID, testset_id))
        entity = self._get_entity_by_id(testset_id)
        list = entity.Name.split('|')
        if list[1] not in osList:
            self.rally.delete("TestSet", entity.oid)
            logger.info('remove testset {}'.format(testset_id))
        # testcasesList = []
        # testcase = self.get_testcase_by_id(testcase_id)
        # testcasesList.append(testcase)
        #
        # try :
        #     self.rally.dropCollectionItems(entity, testcasesList)
        #     logger.info('remove testcase {} from testset {}'.format(testcase.FormattedID, testset_id))
        # except Exception as re :
        #     logger.error('Fail to remove test case {} from test set {}: {}'.format(testcase.FormattedID, re))

    # def add_testresult(self, testcase_id, **info):
    #     logger.info('adding test result to {}'.format(testcase_id))
    #     info['TestCase'] = self.get_testcase_by_id(testcase_id).ref
    #     if not info.has_key('date'):
    #         info['date'] = str(datetime.datetime.utcnow().isoformat())
    #     if not info.has_key('tester'):
    #         info['tester'] = self.get_testcase_by_id(testcase_id).Owner.ref
    #     if not info.has_key('Verdict'):
    #         info['Verdict'] = 'Unexecuted'
    #     if not info.has_key('c_ProductionRelease'):
    #         info['c_ProductionRelease'] = '11.1.2 [2019-Jun-7]'
    #     if not info.has_key('Build'):
    #         info['Build'] = '0.0.0.0'
    #     if not info.has_key('note'):
    #         info['Notes'] = 'this result was added by script automatically'
    #
    #     self.rally.create('TestCaseResult', info)

    def _get_all_tags(self):
        response = self.rally.get('Tag',
                                  fetch="true",
                                  order="Name",
                                  server_ping=False,
                                  isolated_workspace=True)
        return [tag for tag in response]

    def _get_tag_by_name(self, tag_name):
        query = 'Name = "{}"'.format(tag_name)
        response = self.rally.get('Tag',
                                  fetch="true",
                                  query=query,
                                  server_ping=False,
                                  isolated_workspace=True)
        if response.resultCount != 0:
            tag = response.next()
            logger.debug('find tag {}'.format(tag.Name))
            return tag
        else:
            logger.error('can not find Tag with name {}'.format(tag_name))

    def get_tags_by_names(self, *tag_names):
        tags = []
        for tag_name in tag_names:
            tags.append(self._get_tag_by_name(tag_name))

        return tags

    def get_all_tag_names(self):
        return [tag.Name for tag in self._get_all_tags()]

    def create_tag(self, tag_name):
        tag_json = {'Name': tag_name}
        tag = self.rally.create('Tag', tag_json)
        return tag

    # somehow is not working
    def del_tag_by_name(self, tag_name):

        tag = self.get_tag_by_name(tag_name)
        self.rally.delete('Tag', itemIdent=self._get_tag_by_name(tag_name).oid)

    def remove_tags_from_testcase(self, testcase_id, tags):
        self.rally.dropCollectionItems(self.get_testcase_by_id(testcase_id),
                                       self.get_tags_by_names(tags))

    # archive tag will hide the tag from drop down list on rally, it is working..
    def archive_tag(self, tag_name):
        tag = self.get_tag_by_name(tag_name)
        info = {"ObjectID": tag.oid, "Archived": True}
        self.rally.update('Tag', info)

    def add_tags_to_entity(self, entity_id, *tag_names):
        entity = self._get_entity_by_id(entity_id)

        tags = []
        for tag_name in tag_names:
            tags.append(self._get_tag_by_name(tag_name))

        logger.info('adding tags {} to {}'.format(tag_names, entity_id))
        self.rally.addCollectionItems(entity, tags)

    def _get_entity_type(self, entity_id):
        if entity_id.startswith('TC'):
            entity_type = 'TestCase'
        elif entity_id.startswith('US'):
            entity_type = 'UserStory'
        elif entity_id.startswith('DE'):
            entity_type = 'Defect'
        elif entity_id.startswith('TS'):
            entity_type = 'TestSet'
        elif entity_id.startswith('TF'):
            entity_type = 'TestFolder'

        return entity_type

    def _update_entity(self, entity_id, **info):
        entity_type = self._get_entity_type(entity_id)
        info['FormattedID'] = entity_id
        logger.debug('{},{}'.format(entity_type, info))
        self.rally.update(entity_type, info)

    # def update_defect(self, entity_id, **info):
    #     self._update_entity(entity_id = entity_id, info=info)

    def active_testcase(self, testcase_id):
        self._update_entity(testcase_id, c_TestCaseStatus='Active')

    def active_all_testcases_in_testfolder(self, testfolder_id):
        for item in self.get_testcases_from_testfolder(
                testfolder_id=testfolder_id):
            logger.info('activing test case {} {}'.format(
                item.FormattedID, item.Name))
            self.active_testcase(item.FormattedID)

    def set_testcase_type(self, testcase_id, testcase_type):
        self._update_entity(testcase_id, Type=testcase_type)

    def update_testcase_owner(self, testcase_id, owner):
        tc = self.get_testcase_by_id(testcase_id)
        self.testCasefields = {}
        self.testCasefields['ObjectID'] = tc.oid
        self.testCasefields['Owner'] = self.get_user_ref_by_owner(owner)
        try:
            response = self.rally.update('TestCase', self.testCasefields)
            logger.info('Owner for test case {} now become {}'.format(
                tc.FormattedID, response.Owner.Name))
        except Exception as re:
            logger.error('Fail to update test case {}, {}'.format(
                tc.FormattedID, re.message))

    def update_testcase_project(self, testcase_id):
        tc = self.get_testcase_by_id(testcase_id)
        self.testCasefields = {}
        self.testCasefields['ObjectID'] = tc.oid
        self.testCasefields['Project'] = self.rally.getProject().ref
        try:
            response = self.rally.update('TestCase', self.testCasefields)
            logger.info('Project for test case {} now become {}'.format(
                tc.FormattedID, response.Project.Name))
        except Exception as re:
            logger.error('Fail to update test case {}, {}'.format(
                tc.FormattedID, re.message))

    def update_testcase_status(self, testcase_id, testcase_status):
        tc = self.get_testcase_by_id(testcase_id)
        self.testCasefields = {}
        self.testCasefields['ObjectID'] = tc.oid
        self.testCasefields['c_TestCaseStatus'] = testcase_status
        try:
            response = self.rally.update('TestCase', self.testCasefields)
            logger.info('test case for test case {} now become {}'.format(
                tc.FormattedID, response.c_TestCaseStatus))
        except Exception as re:
            logger.error('Fail to update test case {}, {}'.format(
                tc.FormattedID, re.message))

    def update_testset_name(self, testset_id, oldrelease, newrelease):
        ts = self.get_testcase_by_id(testset_id)
        self.testSetfields = {}
        self.testSetfields['ObjectID'] = ts.oid

        self.testSetfields['Name'] = ts.Name.replace(oldrelease, newrelease)
        try:
            response = self.rally.update('TestSet', self.testSetfields)
            logger.info('test set for test set {} now become {}'.format(
                ts.FormattedID, response.Name))
        except Exception as re:
            logger.error('Fail to update test set {}, {}'.format(
                ts.FormattedID, re.message))

    def get_user_ref_by_owner(self, owner):
        owner = owner.split('@')[0] if '@' in owner else owner
        return self.rally.getUserInfo(username=('*****@*****.**' %
                                                owner))[0].ref

    def get_discussion(self, entity_id):
        entity = elf._get_entity_by_id(entity_id)
        discussion_context = []
        if hasattr(entity, '__collection_ref_for_Discussion'):
            discussion_url = entity.__collection_ref_for_Discussion
            content = json.loads(
                ralutil.rally.session.get(discussion_url).content)
            for post in content['QueryResult']['Results']:
                discussion_context.append(post)
        else:
            logger.error('{} has no discussion'.format(entity_id))
            return

    def get_testsets(self):
        query = 'c_ProductionRelease = "11.2 EA [2019-Jun-21]"'
        testsets = self.rally.get('TestSet', query=query, instance=True)
        for testset in testsets:
            print(testset.Name)

    def add_teststeps_to_testcase(self, testcase_id, inputs, expect_results):
        testcase = self.get_testset_by_id(testcase_id)

        if len(inputs) != len(expect_results):
            logger.warning(
                'your input# is not match your expect# {}/{}'.format(
                    len(inputs), len(expect_results)))
        if len(inputs) <= len(expect_results):
            index = len(inputs)
        else:
            index = len(expect_results)
        for i in range(index):
            Step = {'StepIndex': i + 1}
            Step['Input'] = inputs[i]
            Step['ExpectedResult'] = expect_results[i]
            Step['TestCase'] = testcase.ref
            logger.debug(Step)
            self.rally.create('TestCaseStep', Step)

    def add_discussion_to_testcase(self, testcase_id, **info):
        querytestcase = 'TestCase.FormattedID = "%s"' % testcase_id
        testcaseDiscussion = self.rally.get('ConversationPost',
                                            query=querytestcase,
                                            instance=True)
        testcase = self.get_testcase_by_id(testcase_id)
        queryuser = '******' % info['User']
        user = self.rally.get('User',
                              fetch=True,
                              query=queryuser,
                              instance=True)

        info["User"] = user.ref
        info['Artifact'] = testcase.ref
        # info['_type']     = "ConversationPost"

        self.rally.create('ConversationPost', info)

    def clean_teststeps_on_testcase(self, testcase_id):
        testcase = self.get_testset_by_id(testcase_id)

        for step in testcase.Steps:
            self.rally.delete('TestCaseStep', step.oid)