Example #1
0
    def to_xml(self):
        """Return an XML instance of the suite"""

        x = XMLBuilder('testsuite', name=self.name, tests=str(self.ntests), errors=str(self.nerrors), failures=str(self.nfailure), skip=str(self.nskipped))

        for test_case in self.tests:
            classname = test_case.classname
            # sanitize for XML
            text = "" if test_case.text is None else test_case.text
            etype = "" if test_case.etype is None else test_case.etype

            with x.testcase(classname=classname, name=test_case.name,
                            result=test_case.result, etype=etype,
                            text=text):

                if test_case.result == 'failures':
                    x.error(type=test_case.etype, message=test_case.message)
                elif test_case.result == 'failure':
                    x.failure(type=test_case.etype, message=test_case.message)
                elif test_case.result == 'skipped':
                    x.skipped(type=test_case.etype, message=test_case.message)
                elif test_case.result == 'error':
                    x.error(type=test_case.etype, message=test_case.message)
                else:
                    # Successful testcase
                    pass
        return x
Example #2
0
def convert_suite_and_result_to_xunit(suite, result, name="PysivXunitTestSuite"):
    """Custom a test suite and result to XML.

    The name is used to set the xml suitename for jenkins.

    <testsuite errors="1" failures="1" name="1234" skip="1" tests="5">

    :param suite: unittest.TestSuite
    :param result: unittest.TestResult
    :param name:

    :return: XML instance
    """

    # When a test fails in setUpClass, the result is a
    # unittest.suite._ErrorHolder rather than a TestCase. We need to handle
    # those differently.
    def parse_setupclass_error(klass_id):
        """Return what's inside the parentheses."""
        return re.search("(?<=\().*(?=\))", klass_id).group(0)

    # Test cls names/id
    names = 'errors skipped failures'.split()
    klass_results = {}
    for n in names:
        klass_results[n] = []
        for klass, out in getattr(result, n):
            if isinstance(klass, unittest.suite._ErrorHolder):
                klass_results[n].append(parse_setupclass_error(klass.id()))
            else:
                klass_results[n].append(klass.id())

    nskipped = len(klass_results['skipped'])
    nerrors = len(klass_results['errors'])
    nfailures = len(klass_results['failures'])

    def _to_key(test_case):
        # If the test_case is an _ErrorHolder, the key should be parsed from
        # the description. It won't have a _testMethodName
        if isinstance(test_case, unittest.suite._ErrorHolder):
            return parse_setupclass_error(test_case.description)
        m = test_case.__module__
        n = test_case.__class__.__name__
        mn = test_case._testMethodName
        # d = test_case._testMethodDoc
        # return m, n, mn, d
        return ".".join([m, n, mn])

    all_test_cases = {}
    for s in suite:
        if isinstance(s, unittest.suite.TestSuite):
            for tc in s:
                all_test_cases[_to_key(tc)] = None
        else:
            raise TypeError("Unsupported test suite case ({x})".format(x=type(s)))

    ntests = len(all_test_cases)

    # loop over failures, errors, skipped, assign message
    for n in names:
        # get all testcases with state
        ts = getattr(result, n)
        for t, msg in ts:
            k = _to_key(t)
            all_test_cases[k] = msg

    # import ipdb; ipdb.set_trace()

    # Create XML
    x = XMLBuilder('testsuite', name=name, tests=str(ntests),
                   errors=str(nerrors), failures=str(nfailures),
                   skip=str(nskipped))

    for idx, message in all_test_cases.iteritems():
        test_method = idx.split('.')[-1]
        with x.testcase(classname=idx, name=test_method, time="1.000"):
            if idx in klass_results['errors']:
                x.error(type="exceptions.Exception", message=message)
            elif idx in klass_results['failures']:
                x.failure(type="exceptions.Exception", message=message)
            elif idx in klass_results['skipped']:
                # print "skipped", idx
                x.skipped(type="unittest.case.SkipTest", message=message)
            else:
                # print "Success", idx
                pass

    return x