~coreygoldberg/+junk/subunit-web

« back to all changes in this revision

Viewing changes to subunit2html.py

  • Committer: Corey Goldberg
  • Date: 2014-06-04 22:57:02 UTC
  • Revision ID: corey.goldberg@canonical.com-20140604225702-vk2wpxlu30zzwzmw
updates

Show diffs side-by-side

added added

removed removed

Lines of Context:
457
457
        return "%s" % (self.name)
458
458
 
459
459
 
460
 
def slugify(text):
461
 
    text = text.strip().replace(' ', '_')
462
 
    return re.sub(r'(?u)[^-\w.]', '', text)
463
 
 
464
 
 
465
460
class HtmlOutput(testtools.TestResult):
466
461
    """Output test results in html."""
467
462
 
476
471
 
477
472
    def addSuccess(self, test):
478
473
        self.success_count += 1
479
 
        for key, detail in test._details.items():
480
 
            with open(slugify(key), 'wb') as f:
481
 
                f.write(b''.join(detail.iter_bytes()))
482
474
        output = test.shortDescription()
483
475
        if output is None:
484
476
            output = test.id()
505
497
            self.result.append((2, test, output, _exc_str))
506
498
 
507
499
    def addFailure(self, test, err):
508
 
        print(test)
509
500
        self.failure_count += 1
510
501
        _exc_str = self.formatErr(err)
511
502
        output = test.shortDescription()
694
685
        super(HtmlOutput, self).startTestRun()
695
686
 
696
687
 
697
 
class FileAccumulator(testtools.StreamResult):
698
 
 
699
 
    def __init__(self):
700
 
        super(FileAccumulator, self).__init__()
701
 
        self.route_codes = collections.defaultdict(io.BytesIO)
702
 
 
703
 
    def status(self, **kwargs):
704
 
        if kwargs.get('file_name') != 'stdout':
705
 
            return
706
 
        file_bytes = kwargs.get('file_bytes')
707
 
        if not file_bytes:
708
 
            return
709
 
        route_code = kwargs.get('route_code')
710
 
        stream = self.route_codes[route_code]
711
 
        stream.write(file_bytes)
 
688
class FilesResultOutput(HtmlOutput):
 
689
    """Output test results in html."""
 
690
 
 
691
    def __init__(self, html_file='results.html'):
 
692
        super(FilesResultOutput, self).__init__(html_file)
 
693
 
 
694
    def stopTest(self, test):
 
695
        super(FilesResultOutput, self).stopTest(test)
 
696
        self.save_file_attachments(test)
 
697
 
 
698
    def save_file_attachments(self, test):
 
699
        for key, detail in test._details.items():
 
700
            slugged_text = re.sub(r'(?u)[^-\w.]', '', key)
 
701
            file_name = '%s-%s' % (test.id(), slugged_text)
 
702
            if detail.iter_bytes() != [b'']:
 
703
                with open(file_name, 'wb') as f:
 
704
                    for chunk in detail.iter_bytes():
 
705
                        f.write(chunk)
 
706
 
 
707
    def _slugify(text):
 
708
        return re.sub(r'(?u)[^-\w.]', '', text)
712
709
 
713
710
 
714
711
def main():
715
 
    if len(sys.argv) < 2:
716
 
        print("Need at least one argument: path to subunit log.")
717
 
        exit(1)
718
 
    subunit_file = sys.argv[1]
719
 
    if len(sys.argv) > 2:
720
 
        html_file = sys.argv[2]
721
 
    else:
722
 
        html_file = 'results.html'
 
712
    html_file = 'results.html'
 
713
    subunit_file = 'results.sub'
723
714
 
724
 
    html_result = HtmlOutput(html_file)
 
715
    html_result = FilesResultOutput(html_file)
725
716
    stream = open(subunit_file, 'rb')
726
717
 
727
 
    # Feed the subunit stream through both a V1 and V2 parser.
728
 
    # Depends on having the v2 capable libraries installed.
729
 
    # First V2.
730
 
    # Non-v2 content and captured non-test output will be presented as file
731
 
    # segments called stdout.
732
 
    suite = subunit.ByteStreamToStreamResult(stream, non_subunit_name='stdout')
733
 
    # The HTML output code is in legacy mode.
 
718
    suite = subunit.ByteStreamToStreamResult(stream)
734
719
    result = testtools.StreamToExtendedDecorator(html_result)
735
 
    # Divert non-test output
736
 
    accumulator = FileAccumulator()
737
 
    result = testtools.StreamResultRouter(result)
738
 
    result.add_rule(accumulator, 'test_id', test_id=None)
739
720
    result.startTestRun()
740
721
    suite.run(result)
741
 
    # Now reprocess any found stdout content as V1 subunit
742
 
    for bytes_io in accumulator.route_codes.values():
743
 
        bytes_io.seek(0)
744
 
        suite = subunit.ProtocolTestCase(bytes_io)
745
 
        suite.run(html_result)
746
722
    result.stopTestRun()
747
723
 
748
724