Fix return code and lint in subunit_to_junit script (#2937)

The subunit_to_junit script was added in #2927 to leverage the test
results aggregation features in azure pipelines. It converts the subunit
stream result format that stestr natively generates and converts it to
a junitxml format that azure pipelines can understand. This script was
heavily based on the version of subunit2junitxml filter script included
in the upstream python-subunit script. However, the use case for the
filter script is different so some undesired behavior was ported over.
Mainly that the return code mirrors that of the test suite in the
result stream (ie if the test run fails the converter returns non-zero
too). The python-subunit script did this mainly because it was designed
to be run in a pipeline off the test runner as opposed to a separate
stage post-run. However, since our use case for the subunit_to_junit
script is different having this behavior causes result generation task
failures in azure pipelines UI after the test run failed. This is
undesireable because the junitxml generation task was actually
successful it just included failed tests. This commit corrects this by
making the script always return 0 unless there is an internal failure.

At the same time this commit also fixes several code lint issues. Which
includes dropping support for the subunit v1 protocol. The subunit v1
protocol won't ever come up in our use case so there was no reason to
include compat code for that here.
This commit is contained in:
Matthew Treinish 2019-08-08 12:26:53 -04:00 committed by Kevin Krsulich
parent 58ebc7e41c
commit 481832dc21
1 changed files with 11 additions and 17 deletions

View File

@ -21,9 +21,9 @@
import argparse
import sys
from testtools import StreamToExtendedDecorator
from subunit.filters import run_tests_from_stream
from junitxml import JUnitXmlResult
from subunit.filters import run_tests_from_stream
from testtools import StreamToExtendedDecorator
def filter_by_result(result_factory, output_path, passthrough, forward,
@ -46,18 +46,17 @@ def filter_by_result(result_factory, output_path, passthrough, forward,
:param passthrough_subunit: If True, passthrough should be as subunit.
:return: A test result with the results of the run.
"""
if protocol_version == 1:
sys.stderr.write('Subunit protocol version 2 must be used')
sys.exit(1)
if passthrough:
passthrough_stream = sys.stdout
else:
if 1==protocol_version:
passthrough_stream = DiscardStream()
else:
passthrough_stream = None
passthrough_stream = None
if forward:
forward_stream = sys.stdout
elif 1==protocol_version:
forward_stream = DiscardStream()
else:
forward_stream = None
@ -79,15 +78,13 @@ def filter_by_result(result_factory, output_path, passthrough, forward,
def run_filter_script(result_factory, description, post_run_hook=None,
protocol_version=1, passthrough_subunit=True):
protocol_version=1, passthrough_subunit=True):
"""Main function for simple subunit filter scripts.
Many subunit filter scripts take a stream of subunit input and use a
TestResult to handle the events generated by that stream. This function
wraps a lot of the boiler-plate around that by making a script with
options for handling passthrough information and stream forwarding, and
that will exit with a successful return code (i.e. 0) if the input stream
represents a successful test run.
options for handling passthrough information and stream forwarding
:param result_factory: A callable that takes an output stream and returns
a test result that outputs to that stream.
@ -115,14 +112,11 @@ def run_filter_script(result_factory, description, post_run_hook=None,
post_run_hook(result)
if not hasattr(result, 'wasSuccessful'):
result = result.decorated
if result.wasSuccessful():
sys.exit(0)
else:
sys.exit(1)
def main():
run_filter_script(
lambda output:StreamToExtendedDecorator(
lambda output: StreamToExtendedDecorator(
JUnitXmlResult(output)), "Convert to junitxml", protocol_version=2)
if __name__ == '__main__':