Exemplo n.º 1
0
def output_run_results_junit_xml(passing_tests: List[TestRunResult],
                                 failing_tests: List[TestRunResult],
                                 junit_dest: TextIO,
                                 junit_merged_dest: TextIO):
    '''Write results to JUnit XML

    Two versions are produced: a normal version and a merged version. In the
    normal version there is a test suite per unique test name with a different
    test case per seed run. In the merged version there is a single test case
    under the test suite with information for the individual runs merged
    together. This is to aid use of the Azure Pipelines JUnit dashboard, which
    doesn't neatly handle the test suite/test case hierarchy
    '''

    all_tests = passing_tests + failing_tests

    test_suite_info = {}
    for trr in all_tests:
        # test_case_info contains a tuple per unique test name. The first
        # element is a list of junit_xml.TestCase, one per test run with that
        # name. The other merges together all of the test outputs to produce
        # the merged output.
        unmerged, merged = \
            test_suite_info.setdefault(trr.name, ([], {'stdout': '',
                                                       'failures': ''}))
        result_text = gen_test_run_result_text(trr)

        # Create a test case for the TestRunResult. stdout holds the text
        # describing the run. Add the same text to failures if the test failed.
        test_case = junit_xml.TestCase(f'{trr.name}.{trr.seed}')
        test_case.stdout = result_text

        merged['stdout'] += result_text + '\n'

        if not trr.passed:
            test_case.add_failure_info(output=result_text)
            merged['failures'] += result_text

        unmerged.append(test_case)

    # Output the normal JUnit XML
    test_suites = [
        junit_xml.TestSuite(name, test_cases)
        for name, (test_cases, _) in test_suite_info.items()
    ]

    junit_dest.write(junit_xml.to_xml_report_string(test_suites))

    # Output the merged version of the JUnit XML
    merged_test_suites = []

    for name, (_, merged_test_info) in test_suite_info.items():
        test_case = junit_xml.TestCase(name)
        test_case.stdout = merged_test_info['stdout']
        test_case.add_failure_info(output=merged_test_info['failures'])

        merged_test_suites.append(junit_xml.TestSuite(name, [test_case]))

    junit_merged_dest.write(junit_xml.to_xml_report_string(merged_test_suites))
Exemplo n.º 2
0
    def print_matches(self, matches, rules=None, filenames=None):
        """Output all the matches"""

        if not rules:
            return None

        test_cases = []
        for rule in rules.all_rules:
            if not rules.is_rule_enabled(rule):
                if not rule.id:
                    continue
                test_case = TestCase(
                    name='{0} {1}'.format(rule.id, rule.shortdesc))

                if rule.experimental:
                    test_case.add_skipped_info(
                        message='Experimental rule - not enabled')
                else:
                    test_case.add_skipped_info(message='Ignored rule')
                test_cases.append(test_case)
            else:
                test_case = TestCase(name='{0} {1}'.format(
                    rule.id, rule.shortdesc),
                                     allow_multiple_subelements=True,
                                     url=rule.source_url)
                for match in matches:
                    if match.rule.id == rule.id:
                        test_case.add_failure_info(
                            message=self._failure_format(match),
                            failure_type=match.message)
                test_cases.append(test_case)

        test_suite = TestSuite('CloudFormation Lint', test_cases)

        return to_xml_report_string([test_suite], prettyprint=True)
Exemplo n.º 3
0
def format_baseline_for_junit_xml(baseline):
    """
    :type baseline: dict
    :rtype: str
    """
    all_secrets = {}

    for filename, secret_list in baseline['results'].items():
        for secret in secret_list:
            test_case = junit_xml.TestCase(
                name="{}:{}".format(filename, secret["line_number"]))
            test_case.add_failure_info(
                message="Found secret of type {} on line {} in file {}".format(
                    secret["type"], secret["line_number"], filename),
                failure_type=secret["type"])
            if secret["type"] in all_secrets:
                all_secrets[secret["type"]].append(test_case)
            else:
                all_secrets[secret["type"]] = [test_case]

    test_suits = map(
        lambda secret: junit_xml.TestSuite(name=secret[0],
                                           test_cases=secret[1]),
        all_secrets.items())

    return junit_xml.to_xml_report_string(test_suits)
Exemplo n.º 4
0
def write_junitxml(output_junitxml, results):
    """Write output file as JUnitXML format"""
    if not JUNIT_XML_FOUND:
        log = logging.getLogger(__name__ + ".write_junitxml")
        log.warning('junitxml output disabled: the `junit_xml` python module '
                    'is missing.')
        return
    test_cases = []
    duration_re = re.compile('([0-9]+):([0-9]+):([0-9]+).([0-9]+)')
    for vitem in results:
        if vitem.get('Validations'):
            parsed_duration = 0
            test_duration = vitem.get('Duration', '')
            matched_duration = duration_re.match(test_duration)
            if matched_duration:
                parsed_duration = (int(matched_duration[1])*3600
                                   + int(matched_duration[2])*60
                                   + int(matched_duration[3])
                                   + float('0.{}'.format(matched_duration[4])))

            test_stdout = vitem.get('Status_by_Host', '')

            test_case = TestCase('validations', vitem['Validations'],
                                 parsed_duration, test_stdout)
            if vitem['Status'] == 'FAILED':
                test_case.add_failure_info('FAILED')
            test_cases.append(test_case)

    ts = TestSuite("Validations", test_cases)
    with open(output_junitxml, 'w') as output:
        output.write(to_xml_report_string([ts]))
Exemplo n.º 5
0
def create_xml_report(failures, dockerfile_path):
    """Make a full XML report file."""

    test_case = TestCase(
        "Lint " + dockerfile_path,
        classname="dockerlint.main",
    )
    for f in failures:
        test_case.add_failure_info(message=f.__str__())
    ts = TestSuite("dockerlint", test_cases=[test_case])
    return to_xml_report_string([ts])
Exemplo n.º 6
0
def serialize_and_read(test_suites,
                       to_file=False,
                       prettyprint=False,
                       encoding=None):
    """writes the test suite to an XML string and then re-reads it using minidom,
       returning => (test suite element, list of test case elements)"""
    try:
        iter(test_suites)
    except TypeError:
        test_suites = [test_suites]

    if to_file:
        fd, filename = tempfile.mkstemp(text=True)
        os.close(fd)
        with codecs.open(filename, mode="w", encoding=encoding) as f:
            to_xml_report_file(f,
                               test_suites,
                               prettyprint=prettyprint,
                               encoding=encoding)
        print("Serialized XML to temp file [%s]" % filename)
        xmldoc = minidom.parse(filename)
        os.remove(filename)
    else:
        xml_string = to_xml_report_string(test_suites,
                                          prettyprint=prettyprint,
                                          encoding=encoding)
        if PY2:
            assert isinstance(xml_string, unicode)  # noqa: F821
        print("Serialized XML to string:\n%s" % xml_string)
        if encoding:
            xml_string = xml_string.encode(encoding)
        xmldoc = minidom.parseString(xml_string)

    def remove_blanks(node):
        for x in node.childNodes:
            if x.nodeType == minidom.Node.TEXT_NODE:
                if x.nodeValue:
                    x.nodeValue = x.nodeValue.strip()
            elif x.nodeType == minidom.Node.ELEMENT_NODE:
                remove_blanks(x)

    remove_blanks(xmldoc)
    xmldoc.normalize()

    ret = []
    suites = xmldoc.getElementsByTagName("testsuites")[0]
    for suite in suites.getElementsByTagName("testsuite"):
        cases = suite.getElementsByTagName("testcase")
        ret.append((suite, cases))
    return ret
Exemplo n.º 7
0
    def _generate_report(self):
        """ generate a TestSuite report from the collected TaskData and HostData """

        test_cases = []

        for task_uuid, task_data in self._task_data.items():
            if task_data.action == 'setup' and self._include_setup_tasks_in_report == 'false':
                continue

            for host_uuid, host_data in task_data.host_data.items():
                test_cases.append(self._build_test_case(task_data, host_data))

        test_suite = TestSuite(self._playbook_name, test_cases)
        report = to_xml_report_string([test_suite])

        output_file = os.path.join(self._output_dir, '%s-%s.xml' % (self._playbook_name, time.time()))

        with open(output_file, 'wb') as xml:
            xml.write(to_bytes(report, errors='surrogate_or_strict'))
Exemplo n.º 8
0
def test_to_xml_string():
    test_suites = [
        Suite(name="suite1", test_cases=[Case(name="Test1")]),
        Suite(name="suite2", test_cases=[Case(name="Test2")]),
    ]
    xml_string = to_xml_report_string(test_suites)
    if PY2:
        assert isinstance(xml_string, unicode)  # pylint: disable=undefined-variable
    expected_xml_string = textwrap.dedent("""
        <?xml version="1.0" ?>
        <testsuites disabled="0" errors="0" failures="0" tests="2" time="0.0">
        \t<testsuite disabled="0" errors="0" failures="0" name="suite1" skipped="0" tests="1" time="0">
        \t\t<testcase name="Test1"/>
        \t</testsuite>
        \t<testsuite disabled="0" errors="0" failures="0" name="suite2" skipped="0" tests="1" time="0">
        \t\t<testcase name="Test2"/>
        \t</testsuite>
        </testsuites>
    """.strip("\n"))
    assert xml_string == expected_xml_string
Exemplo n.º 9
0
def process_test_results(test_results, output_folder="./", test_labels=None):
    """
    This function writes test results to a file, displays failed tests to stdout,
    and throws an exception if there are test failures.
    """
    label_string = ""
    if test_labels:
        label_string = "with labels: {}".format(str(test_labels))
    test_suites = [
        TestSuite("Open-CE tests for {} {}".format(feedstock, label_string),
                  test_results[feedstock]) for feedstock in test_results
    ]
    with open(os.path.join(output_folder, utils.DEFAULT_TEST_RESULT_FILE),
              'w') as outfile:
        outfile.write(to_xml_report_string(test_suites))
    failed_tests = [
        x for key in test_results for x in test_results[key] if x.is_failure()
    ]
    if failed_tests:
        raise OpenCEError(
            Error.FAILED_TESTS, len(failed_tests),
            str([failed_test.name for failed_test in failed_tests]))
    log.info("All tests passed!")
Exemplo n.º 10
0
    def _export(self, suite: TestSuite, force=False) -> None:
        """
        Export test suite to JUnit xml file
        :param suite: TestSuite to export
        :return: None
        """
        if not suite or len(suite.test_cases) == 0:
            return

        if not self._has_uncollected_fixtures or force:
            values = self._get_parametrize_as_str()
            path = self._report_dir.joinpath(
                self.get_report_file_name(
                    suite_name=suite.name,
                    args=values,
                    custom_filename=self._custom_filename))
            xml_string = to_xml_report_string([suite])

            os.makedirs(self._report_dir, exist_ok=True)
            with open(path, "w") as f:
                f.write(xml_string)

            self.clear_cases()
Exemplo n.º 11
0
    def export_service_logs_to_junit_suites(cls, source_dir: Path,
                                            report_dir: Path):
        suites = list()
        for file in source_dir.glob("logs_assisted-service*.log"):
            suite_name = Path(file).stem.replace("logs_", "")
            log.info(f"Creating test suite from {suite_name}.log")
            test_cases = cls.get_failure_cases(file, suite_name)
            timestamp = test_cases[0].timestamp if test_cases else None
            suites.append(
                TestSuite(name=suite_name,
                          test_cases=test_cases,
                          timestamp=timestamp))

        log.info(f"Generating xml file for {len(suites)} suites")
        xml_report = to_xml_report_string(suites)
        with open(
                report_dir.joinpath(
                    f"junit_log_parser_{str(uuid.uuid4())[:8]}.xml"),
                "w") as f:
            log.info(
                f"Exporting {len(suites)} suites xml-report with {len(xml_report)} characters to {f.name}"
            )
            f.write(xml_report)
Exemplo n.º 12
0
    def collect(self,
                entries: List[Dict[str, str]],
                suite_name: str,
                report_dir: Optional[Path] = None,
                xml_suffix: str = "") -> str:
        report_dir = Utils.get_report_dir(report_dir)

        test_cases = list()
        for entry in entries:
            test_case = self._get_test_case(
                entry, entry.get(self._format.severity_key, None))
            if test_case is not None:
                test_cases.append(test_case)

        report_dir.mkdir(exist_ok=True)
        xml_report = to_xml_report_string(test_suites=[
            TestSuite(name=suite_name,
                      test_cases=test_cases,
                      timestamp=self._get_suite_timestamp(test_cases))
        ])
        file_name = f"{self._report_prefix}_{suite_name}{f'_{xml_suffix}' if xml_suffix else ''}.xml"
        with open(report_dir.joinpath(file_name), "w") as f:
            f.write(xml_report)
            return f.name
Exemplo n.º 13
0
    def export_service_events_to_junit_suite(
            cls,
            source_dir: Path,
            report_dir: Path,
            events_file_name="k8s_events.json"):
        with open(source_dir.joinpath(events_file_name)) as f:
            events_data = json.load(f)

        log.info(
            f"Creating test suite from service events json file - {events_file_name}"
        )
        test_cases = cls.get_event_test_cases(events_data)

        log.info(f"Generating events xml file")
        xml_report = to_xml_report_string(
            test_suites=[TestSuite(name="EVENTS", test_cases=test_cases)])
        with open(
                report_dir.joinpath(
                    f"junit_events_parser_{str(uuid.uuid4())[:8]}.xml"),
                "w") as f:
            log.info(
                f"Exporting events xml-report with {len(test_cases)} events to {f.name}"
            )
            f.write(xml_report)
Exemplo n.º 14
0
    def create_test_output(self, test_suites):
        self.logger.info(to_xml_report_string(test_suites))

        with open(self.output_file, 'w', encoding='utf-8') as f:
            to_xml_report_file(f, test_suites)
            self.logger.info('Junit xml output stored to %s', f.name)
Exemplo n.º 15
0
        result = unittest.TestResult()

        test.run(result)

        case = junit.TestCase(name=str(test))

        for error in result.errors:
            case.add_error_info(message=error[1])
            err_cnt += 1

        for failure in result.failures:
            case.add_failure_info(message=failure[1])
            fail_cnt += 1

        for skip in result.skipped:
            case.add_skipped_info(message=skip[1])

        cases.append(case)

    ts = junit.TestSuite(name="test", test_cases=cases)

    results = junit.to_xml_report_string([ts], encoding="utf-8")

    if opt.output is None:
        print(results)
    else:
        with open(opt.output, "w") as f:
            f.write(results)

    os.sys.exit(err_cnt | fail_cnt)
Exemplo n.º 16
0
                )
                if case.result == TestCase.RESULT_FAIL:
                    logs = None
                    # TODO: is this of any use? (yaml inside xml!)
                    if (case.start_log_line is not None
                            and case.end_log_line is not None):
                        logs = logs_instance.read(self.get_object(),
                                                  case.start_log_line,
                                                  case.end_log_line)
                    tc.add_error_info("failed", output=logs)
                elif case.result == TestCase.RESULT_SKIP:
                    tc.add_skipped_info("skipped")
                cases.append(tc)
            suites.append(junit_xml.TestSuite(suite.name, test_cases=cases))

        data = junit_xml.to_xml_report_string(suites, encoding="utf-8")
        response = HttpResponse(data, content_type="application/xml")
        response["Content-Disposition"] = ("attachment; filename=job_%d.xml" %
                                           self.get_object().id)
        return response

    @detail_route(methods=["get"], suffix="logs")
    def logs(self, request, **kwargs):
        start = safe_str2int(request.query_params.get("start", 0))
        end = safe_str2int(request.query_params.get("end", None))
        try:
            if start == 0 and end is None:
                data = logs_instance.open(self.get_object())
                response = FileResponse(data, content_type="application/yaml")
            else:
                data = logs_instance.read(self.get_object(), start, end)
Exemplo n.º 17
0
 def get_junit_xml_string(ts: List[TestSuite]) -> str:
     return to_xml_report_string(ts)
Exemplo n.º 18
0
def test_to_xml_string_test_suites_not_a_list():
    test_suites = Suite("suite1", [Case("Test1")])

    with pytest.raises(TypeError) as excinfo:
        to_xml_report_string(test_suites)
    assert str(excinfo.value) == "test_suites must be a list of test suites"