Exemple #1
0
 def setUpClass(cls):
     tc1 = TestCase.create(DEFAULT_PROJ,
                           "regression",
                           "regression",
                           caseimportance="high",
                           caselevel="component",
                           caseautomation="notautomated",
                           caseposneg="positive",
                           testtype="functional",
                           subtype1="-")
     cls.NEW_TEST_CASE = tc1.work_item_id
     tc2 = TestCase.create(DEFAULT_PROJ,
                           "regression",
                           "regression",
                           caseimportance="high",
                           caselevel="component",
                           caseautomation="notautomated",
                           caseposneg="positive",
                           testtype="functional",
                           subtype1="-")
     cls.NEW_TEST_CASE2 = tc2.work_item_id
     Plan.create(plan_id=PLAN_ID,
                 plan_name="regression",
                 project_id=DEFAULT_PROJ,
                 parent_id=None,
                 template_id="release")
     cls.NEW_PLAN = PLAN_ID
Exemple #2
0
 def test_009_dynamic_records(self):
     """This test does the following:
     * creates a TestCase
     * creates a TestRun based on the Example template (Dynamic query)
     * verifies that it is a dynamic query
     * updates an test record.
     * reloads
     * verifies that the record has been added
     """
     TestCase.create(DEFAULT_PROJ,
                     TIME_STAMP,
                     "regression",
                     caseimportance="high",
                     caselevel="component",
                     caseautomation="notautomated",
                     caseposneg="positive",
                     testtype="functional",
                     subtype1="-")
     tr = TestRun.create("proj1",
                         "querytest-%s" % TIME_STAMP,
                         "Example",
                         "querytest-%s" % TIME_STAMP,
                         query=TIME_STAMP)
     self.assertEquals(tr.select_test_cases_by, "dynamicQueryResult")
     num_recs = len(tr.records)
     test_case_id = tr.records[0].test_case_id
     tr.update_test_record_by_fields(test_case_id, "blocked", "comment",
                                     tr.logged_in_user_id,
                                     datetime.datetime.now(), 0)
     tr.reload()
     self.assertEquals(num_recs, len(tr.records))
     self.assertEquals(test_case_id, tr.records[0].test_case_id)
     self.assertEquals(tr.records[0].result, "blocked")
Exemple #3
0
 def test_009_create_comment(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     tc.create_comment("This is a comment")
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.comments) == 1)
     comment = tc2.comments[0]
     self.assertEqual(comment.text, "This is a comment")
Exemple #4
0
 def test_008_create_attachment(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     tc.create_attachment(ATTACH_PATH, "Attached File")
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.attachments) == 1)
     attach = tc2.attachments[0]
     self.assertEqual(attach.author, tc2.logged_in_user_id)
     self.assertEqual(attach.title, "Attached File")
Exemple #5
0
def mark_for_deletion(tc, tag):
    if tag in tc.title:
        wi = TestCase(uri=tc.uri)
        wi.title = "stoner-DeleteMe"
        try:
            wi.update()
            print "Changed {} title from {} to {}".format(wi.work_item_id, tc.title, wi.title)
        except:
            print "Failed to change {}".format(wi.work_item_id)
Exemple #6
0
 def test_013_multiple_types(self):
     req = Requirement()
     tc = TestCase()
     with self.assertRaises(AttributeError):
         tc.reqtype
     with self.assertRaises(AttributeError):
         req.caseimportance
     req.title = "req1"
     tc.title = "tc1"
     self.assertNotEqual(req.title, tc.title)
Exemple #7
0
def add_colon_tc(tc):
    parts = tc.title.split()
    if ":" not in tc.title:
        newtitle = parts[0] + " : " + parts[1]
        wi = TestCase(uri=tc.uri)
        wi.title = newtitle
        try:
            wi.update()
            print "Changed title to {}".format(newtitle)
        except:
            print "Failed to update {}".format(wi.title)
    def print_steps_for_testcase(self, case_id):
        tc = TestCase(TestCase.default_project, case_id)
        steps = tc.get_test_steps()

        for step in steps.steps:
            stp = step.values[0].content
            exp = step.values[1].content
            print('TestStep       = %s' % stp)
            print('ExpectedResult = %s\n' % exp)

        if steps.steps is None:
            print('No step for this tesecase!')
Exemple #9
0
    def print_steps_for_testcase(self, case_id):
        tc = TestCase(TestCase.default_project, case_id)
        steps = tc.get_test_steps()

        for step in steps.steps:
            stp = step.values[0].content
            exp = step.values[1].content
            print 'TestStep       = %s' % stp
            print 'ExpectedResult = %s\n' % exp

        if steps.steps is None:
            print 'No step for this tesecase!'
 def test_custom_workitem(self):
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.TEST_CASE_ID)
     self.assertIsNotNone(tc2.caseautomation)
     with self.assertRaises(PylarionLibException):
         tc2.caseautomation = "bad"
     tc2.caseautomation = "automated"
     # check for shared memory issue
     self.assertNotEqual(self.tc.caseautomation, tc2.caseautomation)
     req = Requirement()
     with self.assertRaises(PylarionLibException):
         req.reqtype = "bad"
     req.reqtype = 'functional'
 def test_bad_character(self):
     """this test validates that non UTF-8 characters will cause an error
     """
     test_case = TestCase()
     steps = TestSteps()
     with self.assertRaises(PylarionLibException):  # check _obj_setter
         test_case.status = u"é".encode('latin')
     with self.assertRaises(PylarionLibException):  # check _custom_setter
         test_case.tcmscaseid = u"é".encode('latin')
     with self.assertRaises(PylarionLibException):  # check _regular_setter
         test_case.title = u"é".encode('latin')
     with self.assertRaises(PylarionLibException):  # check _arr_obj_setter
         steps.keys = [u"é".encode('latin')]
Exemple #12
0
 def test_007_add_linked_work_item(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(tc.add_linked_item(self.work_item_id_2, "verifies"))
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.linked_work_items) == 1)
     link = tc2.linked_work_items[0]
     self.assertEqual(link.work_item_id, self.work_item_id_2)
     self.assertEqual(link.role, "verifies")
     req3 = Requirement(project_id=DEFAULT_PROJ,
                        work_item_id=self.work_item_id_2)
     self.assertTrue(len(req3.linked_work_items_derived) == 1)
     link = req3.linked_work_items_derived[0]
     self.assertEqual(link.work_item_id, self.work_item_id)
     self.assertEqual(link.role, "verifies")
    def list_workitems_by_query(self, query, wi_type):
        fields = ['work_item_id', 'title', 'author', 'created']

        if wi_type in ["testcase", "TestCase"]:
            workitem_list = TestCase.query(query, fields)
        elif wi_type in ["requirement", "Requirement"]:
            workitem_list = Requirement.query(query, fields)
        elif wi_type == '':
            workitem_list = TestCase.query(query, fields) + \
                            Requirement.query(query, fields)
        else:
            print("'%s' is invalid. Use testcase or requirement" % wi_type)
            exit(0)

        return workitem_list
Exemple #14
0
 def test_001_query(self):
     results = TestCase.query("project.id:%s AND title:regression" %
                              (DEFAULT_PROJ))
     tc = results[0]
     self.assertIsNone(tc.title)
     results2 = TestCase.query("project.id:%s AND title:regression" %
                               (DEFAULT_PROJ),
                               fields=["work_item_id", "title"])
     tc = results2[0]
     self.assertIsNotNone(tc.title)
     results3 = TestCase.query("project.id:%s AND title:regression" %
                               (DEFAULT_PROJ),
                               fields=["work_item_id", "caseautomation"])
     tc = results3[0]
     self.assertEquals(tc.caseautomation, "notautomated")
Exemple #15
0
 def test_011_edit_approval(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     with self.assertRaises(PylarionLibException):
         tc.edit_approval("invalid user", "approved")
     with self.assertRaises(PylarionLibException):
         tc.edit_approval(tc.logged_in_user_id, "invalid status")
     tc.edit_approval(tc.logged_in_user_id, "approved")
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.approvals) == 1)
     approval = tc2.approvals[0]
     self.assertEqual(approval.status, "approved")
     self.assertEqual(approval.user_id, tc.logged_in_user_id)
Exemple #16
0
 def query_test_case(self, query=None):
     """
     """
     from pylarion.work_item import TestCase as PylTestCase
     if query is None:
         query = "title:{}".format(self.title)
     return PylTestCase.query(query)
Exemple #17
0
 def query_test_case(self, query=None):
     """
     """
     from pylarion.work_item import TestCase as PylTestCase
     if query is None:
         query = "title:{}".format(self.title)
     return PylTestCase.query(query)
def test_run(path, test_run_id, test_template_id, user, project):
    """Execute a test run based on jUnit XML file."""
    results = parse_junit(path)
    try:
        test_run = TestRun(test_run_id, project_id=project)
        click.echo('Test run {0} found.'.format(test_run_id))
    except PylarionLibException as err:
        click.echo(err, err=True)
        click.echo('Creating test run {0}.'.format(test_run_id))
        test_run = TestRun.create(project, test_run_id, test_template_id)

    for result in results:
        test_case_id = '{0}.{1}'.format(result['classname'], result['name'])
        test_case = TestCase.query(test_case_id)
        if len(test_case) == 0:
            click.echo(
                'Was not able to find test case with id {0}, skipping...'.
                format(test_case_id))
            continue
        status = POLARION_STATUS[result['status']]
        work_item_id = test_case[0].work_item_id
        click.echo(
            'Adding test record for test case {0} with status {1}.'.format(
                work_item_id, status))
        try:
            test_run.add_test_record_by_fields(
                test_case_id=work_item_id,
                test_result=status,
                test_comment=result.get('message'),
                executed_by=user,
                executed=datetime.datetime.now(),
                duration=float(result.get('time', '0')))
        except PylarionLibException as err:
            click.echo('Skipping test case {0}.'.format(work_item_id))
            click.echo(err, err=True)
    def setUpClass(cls):
        global TEST_RUN_ID
        cls.doc = Document.create(DEFAULT_PROJ, "Testing", DOC_NAME,
                                  "Attribute_Test", ["testcase"],
                                  "testspecification")
        cls.testrun = TestRun.create(DEFAULT_PROJ, TEST_RUN_ID, "example",
                                     TEST_RUN_TITLE)
        TEST_RUN_ID = cls.testrun.test_run_id
        # arch is a custom field defined by global admins for test runs.
        # It is set here for a test on custom fields that requires at least two
        # valid values. If in the future, this custom field is removed, or the
        # number of valid values is lowered to 1, a different custom field will
        # have to be used.
        valid_values = cls.testrun.get_valid_field_values("arch")
        cls.testrun.arch = valid_values[1]
        cls.testrun.update()

        cls.tc = TestCase.create(DEFAULT_PROJ,
                                 "regression",
                                 "regression",
                                 caseimportance="high",
                                 caselevel="component",
                                 caseautomation="notautomated",
                                 caseposneg="positive",
                                 testtype="functional",
                                 subtype1="-")
        cls.TEST_CASE_ID = cls.tc.work_item_id
    def print_links_for_testcase(self, case_id):
        tc = TestCase(TestCase.default_project, case_id)
        print('ID%-12sRole' % (''))
        print('-------%7s------' % (''))

        for linked in tc.linked_work_items:
            print('%-13s %-13s' % (linked.work_item_id, linked.role))
 def __init__(self, project_name=None, *args, **kwargs):
    if project_name == None:
       self.polarion = TestCase()
       self.project_name = self.polarion.default_project
    else:
       self.project_name = project_name
    # Open a persistent shelf for the default or specified project
    self.shelf = shelve.open(self.project_name)
Exemple #22
0
def add_test_record(result):
    """Task that adds a test result to a test run.

    This task relies on ``OBJ_CACHE`` to get the test run and user objects. The
    object cache is needed since suds objects are not able to be pickled and it
    is not possible to pass them to processes.
    """
    test_run = OBJ_CACHE['test_run']
    user = OBJ_CACHE['user']
    testcases = OBJ_CACHE['testcases']
    junit_test_case_id = '{0}.{1}'.format(result['classname'], result['name'])
    test_case_id = testcases.get(junit_test_case_id)
    if not test_case_id:
        click.echo(
            'Missing ID information for test {0}, using junit test case id...'.
            format(junit_test_case_id))
        test_case_id = junit_test_case_id
    test_case = TestCase.query(test_case_id)
    if len(test_case) == 0:
        click.echo(
            'Was not able to find test case {0} with id {1}, skipping...'.
            format(junit_test_case_id, test_case_id))
        return
    status = POLARION_STATUS[result['status']]
    work_item_id = test_case[0].work_item_id
    click.echo('Adding test record for test case {0} with status {1}.'.format(
        work_item_id, status))
    message = result.get('message', '')
    if message and type(message) == unicode:
        message = message.encode('ascii', 'xmlcharrefreplace')
    try:
        test_run.add_test_record_by_fields(test_case_id=work_item_id,
                                           test_result=status,
                                           test_comment=message,
                                           executed_by=user,
                                           executed=datetime.datetime.now(),
                                           duration=float(
                                               result.get('time', '0')))
    except PylarionLibException as err:
        click.echo('Skipping test case {0}.'.format(work_item_id))
        click.echo(err, err=True)
    except Exception as err:
        click.echo(
            'Error when adding test record for "{test_case_id}" with the '
            'following information:\n'
            'duration="{duration}"'
            'executed="{executed}"\n'
            'executed_by="{executed_by}"\n'
            'test_result="{test_result}"\n'
            'test_comment="{test_comment}"\n'.format(
                test_case_id=work_item_id,
                test_result=status,
                test_comment=message,
                executed_by=user,
                executed=datetime.datetime.now(),
                duration=float(result.get('time', '0'))))
        click.echo(traceback.format_exc(), err=True)
        raise
Exemple #23
0
 def test_014_steps(self):
     test1 = ["Test 1", "Result 1"]
     test2 = ["Test 2", "Result 2"]
     test3 = ["Test 3", "Result 3"]
     ts1 = TestStep()
     ts1.values = test1
     ts2 = TestStep()
     ts2.values = test2
     ts3 = TestStep()
     ts3.values = test3
     set_steps = [ts1, ts2, ts3]
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     tc.set_test_steps(set_steps)
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     get_steps = tc2.get_test_steps()
     self.assertEqual(get_steps.steps[0].values[0].content,
                      ts1.values[0].content)
     self.assertEqual(get_steps.steps[0].values[1].content,
                      ts1.values[1].content)
     self.assertEqual(get_steps.steps[1].values[0].content,
                      ts2.values[0].content)
     self.assertEqual(get_steps.steps[1].values[1].content,
                      ts2.values[1].content)
     self.assertEqual(get_steps.steps[2].values[0].content,
                      ts3.values[0].content)
     self.assertEqual(get_steps.steps[2].values[1].content,
                      ts3.values[1].content)
Exemple #24
0
 def test_013_incident_report_test(self):
     """This test does the following:
     * gets a TestRun
     * gets a TestCase
     * adds test_steps
     * creates a TestRecord
     * populates the TestRecord
     * Fail the testRecord
     * reloads the TestCase
     * Verifies that an Incident Report was Created
     """
     tr = TestRun(project_id=DEFAULT_PROJ, test_run_id=TEST_RUN_ID)
     tests = [["Test 1", "Result 1"], ["Test 2", "Result 2"],
              ["Test 3", "Result 3"]]
     set_steps = []
     for test in tests:
         ts = TestStep()
         ts.values = test
         set_steps.append(ts)
     tc = TestCase(work_item_id=self.NEW_TEST_CASE)
     tc.set_test_steps(set_steps)
     tc.update()
     tc.reload()
     steps = tc.test_steps.steps
     results = []
     for step in steps:
         res = TestStepResult()
         res.result = "failed"
         res.comment = "This is the result"
         results.append(res)
     rec = TestRecord()
     rec.test_step_results = results
     rec.test_case_id = self.NEW_TEST_CASE
     rec.comment = "Incident Report was Created"
     rec.duration = "50.5"
     rec.result = "failed"
     rec.executed_by = tr.logged_in_user_id
     rec.executed = datetime.datetime.now()
     tr.update_test_record_by_object(self.NEW_TEST_CASE, rec)
     tc.reload()
     linked_work_items = tc.linked_work_items_derived
     idx = len(linked_work_items) - 1
     incident = Incident(project_id="proj1",
                         work_item_id=linked_work_items[idx].work_item_id)
     self.assertIsNotNone(incident)
Exemple #25
0
def add_test_record(result):
    """Task that adds a test result to a test run.

    This task relies on ``OBJ_CACHE`` to get the test run and user objects. The
    object cache is needed since suds objects are not able to be pickled and it
    is not possible to pass them to processes.
    """
    test_run = OBJ_CACHE['test_run']
    user = OBJ_CACHE['user']
    test_case_id = '{0}.{1}'.format(result['classname'], result['name'])
    test_case = TestCase.query(test_case_id)
    if len(test_case) == 0:
        click.echo(
            'Was not able to find test case with id {0}, skipping...'
            .format(test_case_id)
        )
        return
    status = POLARION_STATUS[result['status']]
    work_item_id = test_case[0].work_item_id
    click.echo(
        'Adding test record for test case {0} with status {1}.'
        .format(work_item_id, status)
    )
    message = result.get('message', '')
    if message and type(message) == unicode:
        message = message.encode('ascii', 'xmlcharrefreplace')
    try:
        test_run.add_test_record_by_fields(
            test_case_id=work_item_id,
            test_result=status,
            test_comment=message,
            executed_by=user,
            executed=datetime.datetime.now(),
            duration=float(result.get('time', '0'))
        )
    except PylarionLibException as err:
        click.echo('Skipping test case {0}.'.format(work_item_id))
        click.echo(err, err=True)
    except:
        click.echo(
            'Error when adding test record for "{test_case_id}" with the '
            'following information:\n'
            'duration="{duration}"'
            'executed="{executed}"\n'
            'executed_by="{executed_by}"\n'
            'test_result="{test_result}"\n'
            'test_comment="{test_comment}"\n'
            .format(
                test_case_id=work_item_id,
                test_result=status,
                test_comment=message,
                executed_by=user,
                executed=datetime.datetime.now(),
                duration=float(result.get('time', '0'))
            )
        )
        raise
Exemple #26
0
def get_automation_statuses_from_polarion():

    polarion_items = TestCase.query('project.id:{}'.format(
        conf().polarion.project))

    LUT = {stat: set() for stat in POLARION_CASE_AUTOMATION_STATUSES}

    for item in polarion_items:
        test_case = TestCase(uri=item.uri)
        # TODO: Check whether we have the ID as property of test_case
        item_id = extract_polarion_case_ids(item.uri).pop()
        caseautomation = test_case.caseautomation
        print '{} - {}'.format(item_id, caseautomation)
        if caseautomation not in LUT:
            LUT[caseautomation] = set()
        LUT[caseautomation].add(item_id)

    return LUT
Exemple #27
0
def fix_tc_title(tc):
    """
    Need to add RHSM-TC : prefix to the existing testcases

    :param tc:
    :return:
    """
    if tc.title.startswith("RHSM-TC : "):
        print "TestCase already starts with RHSM-TC : "
        return

    newtitle = "RHSM-TC : " + tc.title
    wi = TestCase(uri=tc.uri)
    wi.title = newtitle
    try:
        wi.update()
        print "Changed {} title to {}".format(wi.work_item_id, newtitle)
    except:
        print "Failed to update {}".format(wi.title)
Exemple #28
0
 def test_004_add_approvee(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     with self.assertRaises(PylarionLibException):
         tc.add_approvee("invalid user")
     tc.add_approvee(tc.logged_in_user_id)
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.approvals) == 1)
     approval = tc2.approvals[0]
     self.assertEqual(approval.status, "waiting")
     self.assertEqual(approval.user_id, tc.logged_in_user_id)
Exemple #29
0
def query_test_case(query, fields=None, **kwargs):
    """
    Returns a list of pylarion TestCase objects

    :param query:
    :param fields: an optional list of fields to populate in the returned TestCase objects
                   (by default only work_item_id and title will be populated)
    :return:
    """
    if fields is None:
        fields = ["work_item_id", "title"]
    from pylarion.work_item import TestCase as PylTestCase
    return PylTestCase.query(query, fields=fields, **kwargs)
Exemple #30
0
 def test_003_add_assignee(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     with self.assertRaises(PylarionLibException):
         tc.add_assignee("invalid user")
     self.assertTrue(tc.add_assignee(tc.logged_in_user_id))
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(tc2.assignee)
     self.assertEqual(tc2.assignee[0].user_id, tc2.logged_in_user_id)
Exemple #31
0
 def test_005_add_category(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     with self.assertRaises(PylarionLibException):
         tc.add_category("invalid category")
     self.assertTrue(tc.add_category("filesystems"))
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.categories) == 1)
     cat = tc2.categories[0]
     self.assertEqual(cat.category_id, "filesystems")
Exemple #32
0
 def test_006_add_hyperlink(self):
     # TODO: check if an invalid hyperlink can be passed in.
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     with self.assertRaises(PylarionLibException):
         tc.add_hyperlink(HYPERLINK, "invalid")
     self.assertTrue(tc.add_hyperlink(HYPERLINK, "ref_ext"))
     tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertTrue(len(tc2.hyperlinks) == 1)
     link = tc2.hyperlinks[0]
     self.assertEqual(link.uri, HYPERLINK)
     self.assertEqual(link.role, "ref_ext")
Exemple #33
0
 def setUpClass(cls):
     tc = TestCase.create(DEFAULT_PROJ,
                          "regression",
                          "regression",
                          caseimportance="high",
                          caselevel="component",
                          caseautomation="notautomated",
                          caseposneg="positive",
                          testtype="functional",
                          subtype1="-")
     req = Requirement.create(DEFAULT_PROJ,
                              "regression _link",
                              "regression link",
                              reqtype="functional",
                              severity="should_have")
     cls.work_item_id = tc.work_item_id
     cls.work_item_uri = tc.uri
     cls.work_item_id_2 = req.work_item_id
     cls.work_item_uri_2 = req.uri
Exemple #34
0
def create_new_case(prefix, case_name, topo, document, project):
    """create new case through the name and topo of case"""
    print(green("Create New Testcase NAME:%s, TOPO:%s" % (case_name, topo)))
    if topo == "":
        case_title = "{}: {}".format(prefix, case_name)
    else:
        case_title = "{}: {} FUNC={}".format(prefix, case_name, topo)
    try:
        case_item = TestCase.create(project,
                                    title=case_title,
                                    desc="",
                                    caseimportance="high",
                                    caseautomation="automated",
                                    caseposneg="positive",
                                    caselevel="component",
                                    testtype="functional",
                                    subtype1="-")
        document.move_work_item_here(case_item.work_item_id, None)
    except:
        return create_new_case(prefix, case_name, topo, document, project)
    return case_item.work_item_id
Exemple #35
0
def remove_linked_requirements_from_tests(test_cases):
    """
    Removes all linked Items from TestCase objects in test_Cases

    :param test_cases:
    :return:
    """
    with open("/tmp/tc_delete.txt", "w") as tcd:
        for tc in test_cases:
            tc = TestCase(uri=tc.uri)
            linked_items  = tc.linked_work_items
            for li in linked_items:
                tc.remove_linked_item(li.work_item_id, "verifies")
            tc.title = "DeleteMe"
            if tc.author == "ci-user":
                tc.author = "stoner"
            tcd.write(tc.work_item_id + "\n")
            tcd.flush()
            tc.update()
def test_run(path, test_run_id, test_template_id, user, project):
    """Execute a test run based on jUnit XML file."""
    results = parse_junit(path)
    try:
        test_run = TestRun(test_run_id, project_id=project)
        click.echo('Test run {0} found.'.format(test_run_id))
    except PylarionLibException as err:
        click.echo(err, err=True)
        click.echo('Creating test run {0}.'.format(test_run_id))
        test_run = TestRun.create(project, test_run_id, test_template_id)

    for result in results:
        test_case_id = '{0}.{1}'.format(result['classname'], result['name'])
        test_case = TestCase.query(test_case_id)
        if len(test_case) == 0:
            click.echo(
                'Was not able to find test case with id {0}, skipping...'
                .format(test_case_id)
            )
            continue
        status = POLARION_STATUS[result['status']]
        work_item_id = test_case[0].work_item_id
        click.echo(
            'Adding test record for test case {0} with status {1}.'
            .format(work_item_id, status)
        )
        try:
            test_run.add_test_record_by_fields(
                test_case_id=work_item_id,
                test_result=status,
                test_comment=result.get('message'),
                executed_by=user,
                executed=datetime.datetime.now(),
                duration=float(result.get('time', '0'))
            )
        except PylarionLibException as err:
            click.echo('Skipping test case {0}.'.format(work_item_id))
            click.echo(err, err=True)
Exemple #37
0
def add_test_case(args):
    """Task that creates or updates Test Cases and manages their Requirement.

    This task relies on ``OBJ_CACHE`` to get the collect_only and project
    objects.

    :param args: A tuple where the first element is a path and the second is a
        list of ``TestFunction`` objects mapping the tests from that path.
    """
    path, tests = args
    collect_only = OBJ_CACHE['collect_only']
    project = OBJ_CACHE['project']

    for test in tests:
        # Fetch the test case id if the @Id tag is present otherwise generate a
        # test_case_id based on the test Python import path
        test_case_id = test.unexpected_tags.get('id')
        if not test_case_id:
            # Generate the test_case_id. It could be either path.test_name or
            # path.ClassName.test_name if the test methods is defined within a
            # class.
            test_case_id_parts = [
                path.replace('/', '.').replace('.py', ''),
                test.name
            ]
            if test.parent_class is not None:
                test_case_id_parts.insert(-1, test.parent_class)
            test_case_id = '.'.join(test_case_id_parts)

        if test.docstring:
            if not type(test.docstring) == unicode:
                test.docstring = test.docstring.decode('utf8')
            test.docstring = RST_PARSER.parse(test.docstring)

        # Is the test automated? Acceptable values are:
        # automated, manualonly, and notautomated
        auto_status = test.unexpected_tags.get(
            'caseautomation',
            'automated' if test.automated else 'notautomated'
        ).lower()
        caseposneg = test.unexpected_tags.get(
            'caseposneg',
            'negative' if 'negative' in test.name else 'positive'
        ).lower()
        subtype1 = test.unexpected_tags.get(
            'subtype1',
            '-'
        ).lower()
        casecomponent = test.unexpected_tags.get('casecomponent', '-').lower()
        caseimportance = test.unexpected_tags.get(
            'caseimportance', 'medium').lower()
        caselevel = test.unexpected_tags.get('caselevel', 'component').lower()
        setup = test.setup if test.setup else None
        status = test.unexpected_tags.get('status', 'approved').lower()
        testtype = test.unexpected_tags.get(
            'testtype',
            'functional'
        ).lower()
        upstream = test.unexpected_tags.get('upstream', 'no').lower()

        results = []
        if not collect_only:
            results = TestCase.query(
                test_case_id,
                fields=[
                    'caseautomation',
                    'caseposneg',
                    'description',
                    'work_item_id'
                ]
            )
        requirement_name = test.unexpected_tags.get(
            'requirement', parse_requirement_name(path))
        if len(results) == 0:
            click.echo(
                'Creating test case {0} for requirement {1}.'
                .format(test.name, requirement_name)
            )
            if not collect_only:
                test_case = TestCase.create(
                    project,
                    test.name,
                    test.docstring if test.docstring else '',
                    caseautomation=auto_status,
                    casecomponent=casecomponent,
                    caseimportance=caseimportance,
                    caselevel=caselevel,
                    caseposneg=caseposneg,
                    subtype1=subtype1,
                    test_case_id=test_case_id,
                    testtype=testtype,
                    setup=setup,
                    upstream=upstream,
                )
                test_case.status = status
                test_case.update()
            click.echo(
                'Linking test case {0} to verify requirement {1}.'
                .format(test.name, requirement_name)
            )
            if not collect_only:
                requirement = fetch_requirement(
                    requirement_name, project, collect_only)
                test_case.add_linked_item(
                    requirement.work_item_id, 'verifies')
        else:
            click.echo(
                'Updating test case {0} for requirement {1}.'
                .format(test.name, requirement_name)
            )
            # Ensure that a single match for the Test Case is
            # returned.
            assert len(results) == 1
            test_case = results[0]
            if not collect_only and any((
                    test_case.caseautomation != auto_status,
                    test_case.casecomponent != casecomponent,
                    test_case.caseimportance != caseimportance,
                    test_case.caselevel != caselevel,
                    test_case.caseposneg != caseposneg,
                    test_case.description != test.docstring,
                    test_case.setup != setup,
                    test_case.subtype1 != subtype1,
                    test_case.testtype != testtype,
                    test_case.upstream != upstream,
                    test_case.status != status,
            )):
                test_case.description = (
                    test.docstring if test.docstring else '')
                test_case.caseautomation = auto_status
                test_case.casecomponent = casecomponent
                test_case.caseimportance = caseimportance
                test_case.caselevel = caselevel
                test_case.caseposneg = caseposneg
                test_case.setup = setup
                test_case.status = status
                test_case.subtype1 = subtype1
                test_case.testtype = testtype
                test_case.upstream = upstream
                test_case.update()
def test_case(path, collect_only, project):
    """Sync test cases with Polarion."""
    testcases = testimony.get_testcases([path])
    for path, tests in testcases.items():
        requirement = None
        for test in tests:
            # Expect test_case_id to be path.test_name or
            # path.ClassName.test_name.
            test_case_id_parts = [
                path.replace('/', '.').replace('.py', ''), test.name
            ]
            if test.parent_class is not None:
                test_case_id_parts.insert(-1, test.parent_class)
            test_case_id = '.'.join(test_case_id_parts)
            if requirement is None:
                requirement_name = parse_requirement_name(test_case_id)
                results = Requirement.query('{0}'.format(requirement_name),
                                            fields=['title', 'work_item_id'])
                if len(results) > 0:
                    # As currently is not possible to get a single
                    # match for the title, make sure to not use a
                    # not intended Requirement.
                    for result in results:
                        if result.title == requirement_name:
                            requirement = result

                if requirement is None:
                    click.echo(
                        'Creating requirement {0}.'.format(requirement_name))
                    if not collect_only:
                        requirement = Requirement.create(project,
                                                         requirement_name,
                                                         '',
                                                         reqtype='functional')

            results = TestCase.query(test_case_id,
                                     fields=['description', 'work_item_id'])
            if len(results) == 0:
                click.echo(
                    'Creating test case {0} for requirement {1}.'.format(
                        test.name, requirement_name))
                if not collect_only:
                    test_case = TestCase.create(
                        project,
                        test.name,
                        test.docstring if test.docstring else '',
                        caseautomation='automated',
                        casecomponent='-',
                        caseimportance='medium',
                        caselevel='component',
                        caseposneg='positive',
                        subtype1='-',
                        test_case_id=test_case_id,
                        testtype='functional',
                    )
                click.echo(
                    'Liking test case {0} to verify requirement {1}.'.format(
                        test.name, requirement_name))
                if not collect_only:
                    test_case.add_linked_item(requirement.work_item_id,
                                              'verifies')
            else:
                click.echo(
                    'Updating test case {0} for requirement {1}.'.format(
                        test.name, requirement_name))
                # Ensure that a single match for the Test Case is
                # returned.
                assert len(results) == 1
                test_case = results[0]
                if (not collect_only
                        and test_case.description != test.docstring):
                    test_case = TestCase(project, test_case.work_item_id)
                    test_case.description = (test.docstring
                                             if test.docstring else '')
                    test_case.update()
Exemple #39
0
def edit_tc_title(tc_, prefix):
    tc = TestCase(uri=tc_.uri)
    tc.title += prefix
    tc.update()
def test_case(path, collect_only, project):
    """Sync test cases with Polarion."""
    testcases = testimony.get_testcases([path])
    for path, tests in testcases.items():
        requirement = None
        for test in tests:
            # Expect test_case_id to be path.test_name or
            # path.ClassName.test_name.
            test_case_id_parts = [
                path.replace('/', '.').replace('.py', ''),
                test.name
            ]
            if test.parent_class is not None:
                test_case_id_parts.insert(-1, test.parent_class)
            test_case_id = '.'.join(test_case_id_parts)
            if requirement is None:
                requirement_name = parse_requirement_name(test_case_id)
                results = Requirement.query(
                    '{0}'.format(requirement_name),
                    fields=['title', 'work_item_id']
                )
                if len(results) > 0:
                    # As currently is not possible to get a single
                    # match for the title, make sure to not use a
                    # not intended Requirement.
                    for result in results:
                        if result.title == requirement_name:
                            requirement = result

                if requirement is None:
                    click.echo(
                        'Creating requirement {0}.'.format(requirement_name))
                    if not collect_only:
                        requirement = Requirement.create(
                            project,
                            requirement_name,
                            '',
                            reqtype='functional'
                        )

            results = TestCase.query(
                test_case_id, fields=['description', 'work_item_id'])
            if len(results) == 0:
                click.echo(
                    'Creating test case {0} for requirement {1}.'
                    .format(test.name, requirement_name)
                )
                if not collect_only:
                    test_case = TestCase.create(
                        project,
                        test.name,
                        test.docstring if test.docstring else '',
                        caseautomation='automated',
                        casecomponent='-',
                        caseimportance='medium',
                        caselevel='component',
                        caseposneg='positive',
                        subtype1='-',
                        test_case_id=test_case_id,
                        testtype='functional',
                    )
                click.echo(
                    'Liking test case {0} to verify requirement {1}.'
                    .format(test.name, requirement_name)
                )
                if not collect_only:
                    test_case.add_linked_item(
                        requirement.work_item_id, 'verifies')
            else:
                click.echo(
                    'Updating test case {0} for requirement {1}.'
                    .format(test.name, requirement_name)
                )
                # Ensure that a single match for the Test Case is
                # returned.
                assert len(results) == 1
                test_case = results[0]
                if (not collect_only and
                        test_case.description != test.docstring):
                    test_case = TestCase(project, test_case.work_item_id)
                    test_case.description = (
                        test.docstring if test.docstring else '')
                    test_case.update()
Exemple #41
0
 def test_002_get_item(self):
     tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id)
     self.assertIsNotNone(tc.uri)
Exemple #42
0
def main():

    isUpdateAutomationValue = False
    # access excel file and update results
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?version=v4')
    service = discovery.build('sheets',
                              'v4',
                              http=http,
                              discoveryServiceUrl=discoveryUrl)

    # https://docs.google.com/spreadsheets/d/1y4eBJhcZ0HsB5JUH5MPcFXWtc2zbP9XbgdCIF0S4iHs/edit#gid=1503195790
    spreadsheetId = '1y4eBJhcZ0HsB5JUH5MPcFXWtc2zbP9XbgdCIF0S4iHs'

    # Get all test runs by Polarion query, extract test run id and test run results (pass, fail, pending block, total...)

    test_runs_uris = TestRun.search(
        'NOT status:invalid AND plannedin.KEY:RHOS16'
    )  #updated:[20190627 TO 20190630]') #
    # test_runs_uris = TestRun.search('20180625-0836')
    print("Number of items %s" % len(test_runs_uris))
    loop_counter = 1
    missing_test_run_in_excel = ''
    non_test_cases_item = 0

    for test_run_uri in test_runs_uris:
        # for i in range(106,130):
        #     test_run_uri = test_runs_uris[i]

        #get excel values
        rangeName = 'RHOS 16!A2:X'
        result = service.spreadsheets().values().get(
            spreadsheetId=spreadsheetId, range=rangeName).execute()
        values = result.get('values', [])
        value_input_option = 'RAW'

        print('Updating test run number: ' + str(loop_counter))
        loop_counter += 1

        print(test_run_uri.uri)
        test_run = TestRun(uri=test_run_uri.uri)
        test_run_id = test_run.test_run_id

        print('Test run title: ' + test_run.title)
        print('Test run ID: ' + test_run.test_run_id)

        records = test_run.records
        pass_counter = 0
        fail_counter = 0
        pending_counter = 0
        automation_counter = 0.0
        critical_counter = 0
        critical_auto_counter = 0
        #automation_percentage = 0
        blocked_counter = 0
        total_counter = 0

        #Collect inforamtion about test runs, how many test pass

        if test_run.TestRunType == 'Acceptance':

            for record in records:
                if record.result == 'passed':
                    pass_counter += 1
                elif record.result == 'failed':
                    fail_counter += 1
                elif record.result == 'blocked':
                    blocked_counter += 1
                else:
                    pending_counter += 1
        else:
            for record in records:
                # print record.result
                #check if test is automated

                test = TestCase.query(record.test_case_id)

                # print('Test case ID: ' + record.test_case_id)
                # Check if the object type is a testcase and not a header for example!
                if test and not Requirement.query(record.test_case_id):

                    #calculate critical automated and rest automated
                    if isUpdateAutomationValue:
                        if test[0].caseautomation.lower() == 'automated':
                            automation_counter += 1
                            if test[0].caseimportance.lower() == 'critical':
                                critical_auto_counter += 1
                        #count number of critical cases
                        if test[0].caseimportance.lower() == 'critical':
                            critical_counter += 1

                    if record.result == 'passed':
                        pass_counter += 1
                    elif record.result == 'failed':
                        fail_counter += 1
                    elif record.result == 'blocked':
                        blocked_counter += 1
                    else:
                        pending_counter += 1
                else:
                    non_test_cases_item += 1

        total_counter = pass_counter + fail_counter + blocked_counter + pending_counter
        # if total_counter > 0:
        #     automation_percentage = int(float(automation_counter)/float(total_counter)) #*100

        print('Total pass:'******'Total fail:', fail_counter)
        print('Total blocked:', blocked_counter)
        print('Total pending:', pending_counter)
        print('Total automated:', automation_counter)
        print('Number of critical:', critical_counter)
        print('Number of critical auto:', critical_auto_counter)
        #print ('Automation percentage:', automation_percentage)
        print('Total number of test cases:', total_counter)

        #column number in excel file and thier representation as hard coded value
        row_counter = 1  # offset due to headers
        title_column_number = 2
        total_column_number = 8
        pass_column_number = 9
        fail_column_number = 10
        blocked_column_number = 11
        test_run_id_column_number = 20
        automation_percentage_column_number = 18
        critical_test_number = 22
        is_test_run_exist_in_excel = None

        if not values:
            print('No data found.')
        else:
            for row in values:
                is_test_run_exist_in_excel = False
                row_counter += 1
                # print(row_counter)
                # if(row_counter==134):
                #     print('stop')

                # Check that row contains test run id in cell R AND check that test_run_id is match
                if row.__len__() >= test_run_id_column_number and row[
                        test_run_id_column_number] == test_run_id:
                    print('Row number is: ' + str(row_counter))
                    is_test_run_exist_in_excel = True
                    #  print('%s, %s, %s, %s, %s, %s, %s :' % (row[title_column_number], row[total_column_number], row[pass_column_number], row[fail_column_number], row[blocked_column_number],row[automation_percentage_column_number], row[critical_test_number]))
                    values = [[
                        total_counter, total_counter, pass_counter,
                        fail_counter, blocked_counter
                    ]]
                    body = {'values': values}

                    rangeName = 'RHOS 15!H' + str(row_counter) + ':L' + str(
                        row_counter)
                    result = service.spreadsheets().values().update(
                        spreadsheetId=spreadsheetId,
                        range=rangeName,
                        valueInputOption=value_input_option,
                        body=body).execute()

                    # # update automation percentage field
                    # values = [
                    #     [automation_percentage]
                    # ]
                    # body = {
                    #     'values': values
                    # }
                    # rangeName = 'RHOS 13!S' + str(row_counter)
                    # result = service.spreadsheets().values().update(spreadsheetId=spreadsheetId, range=rangeName, valueInputOption='USER_ENTERED',body=body).execute()

                    # update PQI values...
                    if isUpdateAutomationValue and test_run.TestRunType != 'Acceptance':
                        values = [[
                            automation_counter, critical_counter,
                            critical_auto_counter
                        ]]
                        body = {'values': values}
                        rangeName = 'RHOS 15!V' + str(
                            row_counter) + ':X' + str(row_counter)
                        result = service.spreadsheets().values().update(
                            spreadsheetId=spreadsheetId,
                            range=rangeName,
                            valueInputOption=value_input_option,
                            body=body).execute()

                    # done with update, move to next test run
                    break
        #Check if test run exist in excel file and was updated
        if not is_test_run_exist_in_excel:
            missing_test_run_in_excel += test_run_id + ", "

    print("Missing Test Runs in Excel: " + missing_test_run_in_excel)
    print("Number of headers or requirements in test runs: ",
          non_test_cases_item)
Exemple #43
0
def add_test_case(args):
    """Task that creates or updates Test Cases and manages their Requirement.

    This task relies on ``OBJ_CACHE`` to get the collect_only and project
    objects.

    :param args: A tuple where the first element is a path and the second is a
        list of ``TestFunction`` objects mapping the tests from that path.
    """
    path, tests = args
    collect_only = OBJ_CACHE['collect_only']
    project = OBJ_CACHE['project']

    # Fetch or create a Requirement
    requirement = None
    requirement_name = parse_requirement_name(path)
    click.echo(
        'Fetching requirement {0}.'.format(requirement_name))
    if not collect_only:
        results = Requirement.query(
            '{0}'.format(requirement_name),
            fields=['title', 'work_item_id']
        )
        if len(results) > 0:
            # As currently is not possible to get a single
            # match for the title, make sure to not use a
            # not intended Requirement.
            for result in results:
                if result.title == requirement_name:
                    requirement = result
    if requirement is None:
        click.echo(
            'Creating requirement {0}.'.format(requirement_name))
        if not collect_only:
            requirement = Requirement.create(
                project,
                requirement_name,
                '',
                reqtype='functional'
            )

    for test in tests:
        # Generate the test_case_id. It could be either path.test_name or
        # path.ClassName.test_name if the test methods is defined within a
        # class.
        test_case_id_parts = [
            path.replace('/', '.').replace('.py', ''),
            test.name
        ]
        if test.parent_class is not None:
            test_case_id_parts.insert(-1, test.parent_class)
        test_case_id = '.'.join(test_case_id_parts)

        if test.docstring:
            if not type(test.docstring) == unicode:
                test.docstring = test.docstring.decode('utf8')
            test.docstring = RST_PARSER.parse(test.docstring)

        # Is the test automated? Acceptable values are:
        # automated, manualonly, and notautomated
        auto_status = 'automated' if test.automated else 'notautomated'
        caseposneg = 'negative' if 'negative' in test.name else 'positive'
        setup = test.setup if test.setup else None

        results = []
        if not collect_only:
            results = TestCase.query(
                test_case_id,
                fields=[
                    'caseautomation',
                    'caseposneg',
                    'description',
                    'work_item_id'
                ]
            )
        if len(results) == 0:
            click.echo(
                'Creating test case {0} for requirement {1}.'
                .format(test.name, requirement_name)
            )
            if not collect_only:
                test_case = TestCase.create(
                    project,
                    test.name,
                    test.docstring if test.docstring else '',
                    caseautomation=auto_status,
                    casecomponent='-',
                    caseimportance='medium',
                    caselevel='component',
                    caseposneg=caseposneg,
                    subtype1='-',
                    test_case_id=test_case_id,
                    testtype='functional',
                    setup=setup,
                )
            click.echo(
                'Linking test case {0} to verify requirement {1}.'
                .format(test.name, requirement_name)
            )
            if not collect_only:
                test_case.add_linked_item(
                    requirement.work_item_id, 'verifies')
        else:
            click.echo(
                'Updating test case {0} for requirement {1}.'
                .format(test.name, requirement_name)
            )
            # Ensure that a single match for the Test Case is
            # returned.
            assert len(results) == 1
            test_case = results[0]
            if (not collect_only and
                (test_case.description != test.docstring or
                    test_case.caseautomation != auto_status or
                    test_case.caseposneg != caseposneg or
                    test_case.setup != setup)):
                test_case.description = (
                    test.docstring if test.docstring else '')
                test_case.caseautomation = auto_status
                test_case.caseposneg = caseposneg
                test_case.setup = setup
                test_case.update()
Exemple #44
0
    def create_polarion_tc(self):
        """
        Given the pong.TestCase, convert it to the equivalent pylarion.work_item.TestCase
        """
        t = lambda x: unicode.encode(x, encoding="utf-8", errors="ignore") if isinstance(x, unicode) else x
        desc, title = [t(x) for x in [self.description, self.title]]
        # Check to see if we already have an existing test case
        tc = None
        if self.polarion_tc:
            log.info("Getting TestCase for {}: {}".format(title, desc))
            tc = self.polarion_tc
            self.validate_test(tc)

            if not self.polarion_tc.title.startswith(self.prefix):
                self.polarion_tc.title = self.prefix + self.polarion_tc.title

            # See if the Polarion Test Case has steps. The TestCase will contain a TestSteps array of size 1
            # The step will have 2 columns (or key-value pairs)
            # | step | expectedResult
            # +======+===============
            # | args | PASS
            test_steps = tc.get_test_steps()
            steps = test_steps.steps

            # If this TestCase has more than 1 TestStep, it's the older workaround where a TestStep was a row
            # of data in the 2d array.  Moving to the SR2 2015 release with parameterized testing instead
            if len(steps) > 1:
                tc.set_test_steps()  # Empty the TestSteps
            if len(steps) == 0:
                step = self.make_polarion_test_step()
                tc.set_test_steps([step])
        else:
            log.info("Generating new TestCase for {} : {}".format(title, desc))
            WORKAROUND_949 = False
            try:
                self.description.decode(encoding="utf-8")
            except UnicodeError:
                raw = self.description.encode("utf-8")
                self.description = unicode(raw, encoding="utf-8", errors="replace")
                try:
                    self.description.decode(encoding="utf-8")
                except UnicodeError:
                    WORKAROUND_949 = True

            if WORKAROUND_949:
                self.description = unicode("", encoding="utf-8")

            from pylarion.work_item import TestCase as PylTestCase
            tc = PylTestCase.create(self.project, self.title, self.description, **TC_KEYS)

            # Create PylTestSteps if needed and add it
            if self.step_results:
                step = self.make_polarion_test_step()
                tc.set_test_steps([step])

            if not tc:
                raise Exception("Could not create TestCase for {}".format(self.title))
            else:
                self.polarion_tc = tc

        self.link_requirements(tc)
        self.polarion_tc.update()
        return tc
Exemple #45
0
def add_test_case(args):
    """Task that creates or updates Test Cases and manages their Requirement.

    This task relies on ``OBJ_CACHE`` to get the collect_only and project
    objects.

    :param args: A tuple where the first element is a path and the second is a
        list of ``TestFunction`` objects mapping the tests from that path.
    """
    path, tests = args
    collect_only = OBJ_CACHE['collect_only']
    project = OBJ_CACHE['project']

    for test in tests:
        # Fetch the test case id if the @Id tag is present otherwise generate a
        # test_case_id based on the test Python import path
        test_case_id = test.tokens.get('id', generate_test_id(test))
        if test.docstring:
            if not type(test.docstring) == unicode:
                test.docstring = test.docstring.decode('utf8')

        # Is the test automated? Acceptable values are:
        # automated, manualonly, and notautomated
        auto_status = test.tokens.get(
            'caseautomation',
            'notautomated' if test.tokens.get('status') else 'automated'
        ).lower()
        caseposneg = test.tokens.get(
            'caseposneg',
            'negative' if 'negative' in test.name else 'positive'
        ).lower()
        subtype1 = test.tokens.get(
            'subtype1',
            '-'
        ).lower()
        casecomponent = test.tokens.get('casecomponent', '-').lower()
        caseimportance = test.tokens.get(
            'caseimportance', 'medium').lower()
        caselevel = test.tokens.get('caselevel', 'component').lower()
        description = test.tokens.get(
            'description', test.docstring if test.docstring else '')
        description = RST_PARSER.parse(description)
        setup = test.tokens.get('setup')
        status = test.tokens.get('status', 'approved').lower()
        testtype = test.tokens.get(
            'testtype',
            'functional'
        ).lower()
        title = test.tokens.get('title', test.name)
        upstream = test.tokens.get('upstream', 'no').lower()
        steps = test.tokens.get('steps')
        expectedresults = test.tokens.get('expectedresults')

        if steps and expectedresults:
            test_steps = generate_test_steps(
                map_steps(steps, expectedresults))
        else:
            test_steps = None

        results = []
        if not collect_only:
            results = TestCase.query(
                test_case_id,
                fields=[
                    'caseautomation',
                    'caseposneg',
                    'description',
                    'work_item_id'
                ]
            )
        requirement_name = test.tokens.get(
            'requirement', parse_requirement_name(path))
        if len(results) == 0:
            click.echo(
                'Creating test case {0} for requirement: {1}.'
                .format(title, requirement_name)
            )
            if not collect_only:
                test_case = TestCase.create(
                    project,
                    title,
                    description,
                    caseautomation=auto_status,
                    casecomponent=casecomponent,
                    caseimportance=caseimportance,
                    caselevel=caselevel,
                    caseposneg=caseposneg,
                    setup=setup,
                    subtype1=subtype1,
                    test_case_id=test_case_id,
                    testtype=testtype,
                    upstream=upstream,
                )
                test_case.status = status
                if test_steps:
                    test_case.test_steps = test_steps
                test_case.update()
            click.echo(
                'Linking test case {0} to requirement: {1}.'
                .format(title, requirement_name)
            )
            if not collect_only:
                requirement = fetch_requirement(
                    requirement_name, project, collect_only)
                test_case.add_linked_item(
                    requirement.work_item_id, 'verifies')
        else:
            click.echo(
                'Updating test case {0} for requirement {1}.'
                .format(title, requirement_name)
            )
            # Ensure that a single match for the Test Case is
            # returned.
            assert len(results) == 1
            test_case = results[0]
            if not collect_only and any((
                    test_case.caseautomation != auto_status,
                    test_case.casecomponent != casecomponent,
                    test_case.caseimportance != caseimportance,
                    test_case.caselevel != caselevel,
                    test_case.caseposneg != caseposneg,
                    test_case.description != description,
                    test_case.setup != setup,
                    test_case.status != status,
                    test_case.subtype1 != subtype1,
                    test_case.test_steps != test_steps,
                    test_case.testtype != testtype,
                    test_case.title != title,
                    test_case.upstream != upstream,
            )):
                test_case.caseautomation = auto_status
                test_case.casecomponent = casecomponent
                test_case.caseimportance = caseimportance
                test_case.caselevel = caselevel
                test_case.caseposneg = caseposneg
                test_case.description = description
                test_case.setup = setup
                test_case.status = status
                test_case.subtype1 = subtype1
                test_case.testtype = testtype
                test_case.title = title
                test_case.upstream = upstream
                if test_steps:
                    test_case.test_steps = test_steps
                test_case.update()
class PolarionMapping(collections.MutableMapping):
   lucene_special_chars = ['+', '-', '&&', '||', '!', '(', ')', '{', '}', '[', ']', '^', '\"', '~', '*', '?', ':', '\\']
   
   def __init__(self, project_name=None, *args, **kwargs):
      if project_name == None:
         self.polarion = TestCase()
         self.project_name = self.polarion.default_project
      else:
         self.project_name = project_name
      # Open a persistent shelf for the default or specified project
      self.shelf = shelve.open(self.project_name)

   def __del__(self):
      # Closing the shelf flushes and saves it
      self.shelf.close()

   def __getitem__(self, key):
      if self.shelf.has_key(key):
         return self.shelf.__getitem__(key)
      else:
         # Query Polarion for the test case if it isn't in the shelf
         tests = self.polarion.query("testCaseID:%s OR title:%s" % (self.escape_query(key), self.escape_query(key)), fields=["work_item_id", "title"], project_id=self.project_name)
         if len(tests) == 0:
            print "Test case '%s' does not exist in Polarion" % key
            return None
         elif len(tests) == 1:
            self.shelf[str(key)] = str(tests[0].work_item_id)
            self.shelf.sync()
            return self.shelf.__getitem__(key)
         else:
            err_str = "Found multiple test cases with testCaseID '%s' in Polarion\n" % key
            for tc in tests:
               if tc.test_case_id is not None:
                  err_str += "testCaseID: '%s'; workItemID: '%s'\n" % (tc.test_case_id, tc.work_item_id)
               elif tc.title is not None:
                  err_str += "title: '%s'; workItemID: '%s'\n" % (tc.title, tc.work_item_id)
            raise RuntimeError(err_str)

   def __setitem__(self, key, val):
      self.shelf[str(key)] = str(val)
      self.shelf.sync()
      
   def __delitem__(self, key):
      self.shelf.pop(key, None)
   
   def __iter__(self):
      return self.shelf.__iter__()
   
   def __len__(self):
      return len(self.shelf)

   def __repr__(self):
      return self.shelf.__repr__()

   def escape_query(self, query_str):
      '''Escape Lucene Query Syntax Special Characters'''
      for char in self.lucene_special_chars:
         escape_str = query_str.replace(char, '\%s' % char)
      return escape_str

   def sync(self, full=False):
      '''Sync the mapping with Polarion. If full is True, then do a complete re-sync.'''
      tests = self.polarion.query("", fields=["work_item_id", "title"], project_id=self.project_name)
      if full:
         self.shelf.clear()
      for test in tests:
         if test.test_case_id is not None and not self.shelf.has_key(str(test.test_case_id)):
            print "Adding '%s' with ID '%s'" % (test.test_case_id, test.work_item_id)
            self.shelf[str(test.test_case_id)] = str(test.work_item_id)
         elif test.title is not None and not self.shelf.has_key(str(test.title)):
            print "Adding '%s' with ID '%s'" % (test.title, test.work_item_id)
            self.shelf[str(test.title)] = str(test.work_item_id)
      self.shelf.sync()