示例#1
0
文件: export.py 项目: happz/tmt
def export_to_nitrate(test, create, general):
    """ Export fmf metadata to nitrate test cases """
    import_nitrate()

    new_test_created = False
    # Check nitrate test case
    try:
        nitrate_id = test.node.get('extra-nitrate')[3:]
        nitrate_case = nitrate.TestCase(int(nitrate_id))
        echo(style(f"Test case '{nitrate_case.identifier}' found.", fg='blue'))
    except TypeError:
        # Create a new nitrate test case
        if create:
            nitrate_case = create_nitrate_case(test)
            new_test_created = True
        else:
            raise ConvertError("Nitrate test case id not found.")

    # Summary
    summary = test.node.get('extra-summary',
                            test.node.get('extra-task', test.summary))
    if summary:
        nitrate_case.summary = summary
        echo(style('summary: ', fg='green') + summary)
    else:
        raise ConvertError("Nitrate case summary could not be determined.")

    # Script
    if test.node.get('extra-task'):
        nitrate_case.script = test.node.get('extra-task')
        echo(style('script: ', fg='green') + test.node.get('extra-task'))

    # Components
    # First remove any components that are already there
    nitrate_case.components.clear()
    # Then add fmf ones
    if test.component:
        echo(style('components: ', fg='green') + ' '.join(test.component))
        for component in test.component:
            try:
                nitrate_case.components.add(
                    nitrate.Component(name=component,
                                      product=DEFAULT_PRODUCT.id))
            except nitrate.xmlrpc_driver.NitrateError as error:
                log.debug(error)
                echo(style(f"Failed to add component '{component}'.",
                           fg='red'))
            if general:
                try:
                    general_plan = find_general_plan(component)
                    nitrate_case.testplans.add(general_plan)
                except nitrate.NitrateError as error:
                    log.debug(error)
                    echo(
                        style(
                            f"Failed to link general test plan for '{component}'.",
                            fg='red'))

    # Tags
    nitrate_case.tags.clear()
    # Convert 'tier' attribute into a Tier tag
    if test.tier is not None:
        test.tag.append(f"Tier{test.tier}")
    # Add special fmf-export tag
    test.tag.append('fmf-export')
    nitrate_case.tags.add([nitrate.Tag(tag) for tag in test.tag])
    echo(style('tags: ', fg='green') + ' '.join(set(test.tag)))

    # Default tester
    if test.contact:
        # Need to pick one value, so picking the first contact
        email_address = email.utils.parseaddr(test.contact[0])[1]
        # TODO handle nitrate user not existing and other possible exceptions
        nitrate_case.tester = nitrate.User(email_address)
        echo(style('default tester: ', fg='green') + email_address)

    # Duration
    nitrate_case.time = test.duration
    echo(style('estimated time: ', fg='green') + test.duration)

    # Status
    current_status = nitrate_case.status
    # Enable enabled tests
    if test.enabled:
        nitrate_case.status = nitrate.CaseStatus('CONFIRMED')
        echo(style('status: ', fg='green') + 'CONFIRMED')
    # Disable disabled tests which are CONFIRMED
    elif current_status == nitrate.CaseStatus('CONFIRMED'):
        nitrate_case.status = nitrate.CaseStatus('DISABLED')
        echo(style('status: ', fg='green') + 'DISABLED')
    # Keep disabled tests in their states
    else:
        echo(style('status: ', fg='green') + str(current_status))

    # Environment
    if test.environment:
        environment = ' '.join(tmt.utils.shell_variables(test.environment))
        nitrate_case.arguments = environment
        echo(style('arguments: ', fg='green') + environment)
    else:
        # FIXME unable clear to set empty arguments
        # (possibly error in xmlrpc, BZ#1805687)
        nitrate_case.arguments = ' '
        echo(style('arguments: ', fg='green') + "' '")

    # Structured Field
    struct_field = tmt.utils.StructuredField(nitrate_case.notes)
    echo(style('Structured Field: ', fg='green'))

    # Mapping of structured field sections to fmf case attributes
    section_to_attr = {
        'relevancy': test.relevancy,
        'description': test.summary,
        'purpose-file': test.description,
        'hardware': test.node.get('extra-hardware'),
        'pepa': test.node.get('extra-pepa'),
    }
    for section, attribute in section_to_attr.items():
        if attribute is None:
            try:
                struct_field.remove(section)
            except tmt.utils.StructuredFieldError:
                pass
        else:
            struct_field.set(section, attribute)
            echo(style(section + ': ', fg='green') + attribute.strip())

    # fmf identifer
    fmf_id = test.fmf_id
    struct_field.set('fmf', yaml.dump(fmf_id))
    echo(style('fmf id:\n', fg='green') + yaml.dump(fmf_id).strip())

    # Warning
    if WARNING not in struct_field.header():
        struct_field.header(WARNING + struct_field.header())
        echo(style('Added warning about porting to case notes.', fg='green'))

    # Saving case.notes with edited StructField
    nitrate_case.notes = struct_field.save()

    # Update nitrate test case
    nitrate_case.update()
    echo(
        style("Test case '{0}' successfully exported to nitrate.".format(
            nitrate_case.identifier),
              fg='magenta'))

    # Write id of newly created nitrate case to its file
    if new_test_created:
        fmf_file_path = test.node.sources[-1]
        try:
            with open(fmf_file_path, encoding='utf-8') as fmf_file:
                content = yaml.safe_load(fmf_file)
        except IOError:
            raise ConvertError("Unable to open '{0}'.".format(fmf_file_path))

        content['extra-nitrate'] = nitrate_case.identifier
        tmt.convert.write(fmf_file_path, content)
示例#2
0
文件: export.py 项目: pkis/tmt
def export_to_nitrate(test):
    """ Export fmf metadata to nitrate test cases """
    import_nitrate()
    new_test_created = False

    # Check command line options
    create = test.opt('create')
    general = test.opt('general')
    duplicate = test.opt('duplicate')
    link_bugzilla = test.opt('bugzilla')

    if link_bugzilla:
        import_bugzilla()
        try:
            bz_instance = bugzilla.Bugzilla(url=BUGZILLA_XMLRPC_URL)
        except Exception as exc:
            log.debug(traceback.format_exc())
            raise ConvertError("Couldn't initialize the Bugzilla client.",
                               original=exc)
        if not bz_instance.logged_in:
            raise ConvertError(
                "Not logged to Bugzilla, check `man bugzilla` section "
                "'AUTHENTICATION CACHE AND API KEYS'.")

    # Check nitrate test case
    try:
        nitrate_id = test.node.get('extra-nitrate')[3:]
        nitrate_case = nitrate.TestCase(int(nitrate_id))
        nitrate_case.summary  # Make sure we connect to the server now
        echo(style(f"Test case '{nitrate_case.identifier}' found.", fg='blue'))
    except TypeError:
        # Create a new nitrate test case
        if create:
            nitrate_case = None
            # Check for existing Nitrate tests with the same fmf id
            if not duplicate:
                testcases = _nitrate_find_fmf_testcases(test)
                try:
                    # Select the first found testcase if any
                    nitrate_case = next(testcases)
                except StopIteration:
                    pass
            if not nitrate_case:
                nitrate_case = create_nitrate_case(test)
            new_test_created = True
            # Newly created tmt tests have special format summary
            test._metadata['extra-summary'] = nitrate_case.summary
        else:
            raise ConvertError(f"Nitrate test case id not found for {test}"
                               " (You can use --create option to enforce"
                               " creating testcases)")
    except (nitrate.NitrateError, gssapi.raw.misc.GSSError) as error:
        raise ConvertError(error)

    # Summary
    summary = (test._metadata.get('extra-summary')
               or test._metadata.get('extra-task') or test.summary
               or test.name)
    if summary:
        nitrate_case.summary = summary
        echo(style('summary: ', fg='green') + summary)
    else:
        raise ConvertError("Nitrate case summary could not be determined.")

    # Script
    if test.node.get('extra-task'):
        nitrate_case.script = test.node.get('extra-task')
        echo(style('script: ', fg='green') + test.node.get('extra-task'))

    # Components
    # First remove any components that are already there
    nitrate_case.components.clear()
    if general:
        # Remove also all general plans linked to testcase
        for nitrate_plan in [plan for plan in nitrate_case.testplans]:
            if nitrate_plan.type.name == "General":
                nitrate_case.testplans.remove(nitrate_plan)
    # Then add fmf ones
    if test.component:
        echo(style('components: ', fg='green') + ' '.join(test.component))
        for component in test.component:
            try:
                nitrate_case.components.add(
                    nitrate.Component(name=component,
                                      product=DEFAULT_PRODUCT.id))
            except nitrate.xmlrpc_driver.NitrateError as error:
                log.debug(error)
                echo(style(f"Failed to add component '{component}'.",
                           fg='red'))
            if general:
                try:
                    general_plan = find_general_plan(component)
                    nitrate_case.testplans.add(general_plan)
                except nitrate.NitrateError as error:
                    log.debug(error)
                    echo(
                        style(
                            f"Failed to link general test plan for '{component}'.",
                            fg='red'))

    # Tags
    nitrate_case.tags.clear()
    # Convert 'tier' attribute into a Tier tag
    if test.tier is not None:
        test.tag.append(f"Tier{test.tier}")
    # Add special fmf-export tag
    test.tag.append('fmf-export')
    nitrate_case.tags.add([nitrate.Tag(tag) for tag in test.tag])
    echo(style('tags: ', fg='green') + ' '.join(set(test.tag)))

    # Default tester
    if test.contact:
        # Need to pick one value, so picking the first contact
        email_address = email.utils.parseaddr(test.contact[0])[1]
        # TODO handle nitrate user not existing and other possible exceptions
        nitrate_case.tester = nitrate.User(email_address)
        echo(style('default tester: ', fg='green') + email_address)

    # Duration
    nitrate_case.time = test.duration
    echo(style('estimated time: ', fg='green') + test.duration)

    # Manual
    nitrate_case.automated = not test.manual
    echo(style('automated: ', fg='green') + ['auto', 'manual'][test.manual])

    # Status
    current_status = nitrate_case.status
    # Enable enabled tests
    if test.enabled:
        nitrate_case.status = nitrate.CaseStatus('CONFIRMED')
        echo(style('status: ', fg='green') + 'CONFIRMED')
    # Disable disabled tests which are CONFIRMED
    elif current_status == nitrate.CaseStatus('CONFIRMED'):
        nitrate_case.status = nitrate.CaseStatus('DISABLED')
        echo(style('status: ', fg='green') + 'DISABLED')
    # Keep disabled tests in their states
    else:
        echo(style('status: ', fg='green') + str(current_status))

    # Environment
    if test.environment:
        environment = ' '.join(tmt.utils.shell_variables(test.environment))
        nitrate_case.arguments = environment
        echo(style('arguments: ', fg='green') + environment)
    else:
        # FIXME unable clear to set empty arguments
        # (possibly error in xmlrpc, BZ#1805687)
        nitrate_case.arguments = ' '
        echo(style('arguments: ', fg='green') + "' '")

    # Structured Field
    struct_field = tmt.utils.StructuredField(nitrate_case.notes)
    echo(style('Structured Field: ', fg='green'))

    # Mapping of structured field sections to fmf case attributes
    section_to_attr = {
        'description': test.summary,
        'purpose-file': test.description,
        'hardware': test.node.get('extra-hardware'),
        'pepa': test.node.get('extra-pepa'),
    }
    for section, attribute in section_to_attr.items():
        if attribute is None:
            try:
                struct_field.remove(section)
            except tmt.utils.StructuredFieldError:
                pass
        else:
            struct_field.set(section, attribute)
            echo(style(section + ': ', fg='green') + attribute.strip())

    # fmf identifer
    fmf_id = tmt.utils.dict_to_yaml(test.fmf_id)
    struct_field.set('fmf', fmf_id)
    echo(style('fmf id:\n', fg='green') + fmf_id.strip())

    # Warning
    if WARNING not in struct_field.header():
        struct_field.header(WARNING + struct_field.header())
        echo(style('Add migration warning to the test case notes.',
                   fg='green'))

    # Saving case.notes with edited StructField
    nitrate_case.notes = struct_field.save()

    # Export manual test instructions from *.md file to nitrate as html
    md_path = return_markdown_file()
    if os.path.exists(md_path):
        step, expect, setup, cleanup = convert_manual_to_nitrate(md_path)
        nitrate.User()._server.TestCase.store_text(nitrate_case.id, step,
                                                   expect, setup, cleanup)
        echo(style(f"manual steps:", fg='green') + f" found in {md_path}")

    # Append id of newly created nitrate case to its file
    if new_test_created:
        echo(style(f"Append the nitrate test case id.", fg='green'))
        try:
            with test.node as data:
                data["extra-nitrate"] = nitrate_case.identifier
        except AttributeError:
            # FIXME: Remove this deprecated code after fmf support
            # for storing modified data is released long enough
            file_path = test.node.sources[-1]
            try:
                with open(file_path, encoding='utf-8', mode='a+') as file:
                    file.write(f"extra-nitrate: {nitrate_case.identifier}\n")
            except IOError:
                raise ConvertError("Unable to open '{0}'.".format(file_path))

    # List of bugs test verifies
    verifies_bug_ids = []
    for link in test.link:
        try:
            verifies_bug_ids.append(
                int(re.search(RE_BUGZILLA_URL, link['verifies']).group(1)))
        except Exception as err:
            log.debug(err)

    # Add bugs to the Nitrate case
    for bug_id in verifies_bug_ids:
        nitrate_case.bugs.add(nitrate.Bug(bug=int(bug_id)))

    # Update nitrate test case
    nitrate_case.update()
    echo(
        style("Test case '{0}' successfully exported to nitrate.".format(
            nitrate_case.identifier),
              fg='magenta'))

    # Optionally link Bugzilla to Nitrate case
    if link_bugzilla and verifies_bug_ids:
        try:
            bz_set_coverage(bz_instance, verifies_bug_ids,
                            int(nitrate_case.id))
            echo(
                style("Linked to Bugzilla: {}.".format(" ".join(
                    [f"BZ#{bz_id}" for bz_id in verifies_bug_ids])),
                      fg='magenta'))
        except Exception as err:
            raise ConvertError("Couldn't update bugs", original=err)