1 # subunit: extensions to python unittest to get test results from subprocesses.
2 # Copyright (C) 2009 Robert Collins <robertc@robertcollins.net>
4 # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
5 # license at the users choice. A copy of both licenses are available in the
6 # project source as Apache-2.0 and BSD. You may not use this file except in
7 # compliance with one of these two licences.
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # license you chose for the specific language governing permissions and
13 # limitations under that license.
17 from optparse import OptionParser
20 from subunit import DiscardStream, ProtocolTestCase
23 def make_options(description):
24 parser = OptionParser(description=description)
26 "--no-passthrough", action="store_true",
27 help="Hide all non subunit input.", default=False,
28 dest="no_passthrough")
31 help="Send the output to this path rather than stdout.")
33 "-f", "--forward", action="store_true", default=False,
34 help="Forward subunit stream on stdout.")
38 def run_tests_from_stream(input_stream, result, passthrough_stream=None,
40 """Run tests from a subunit input stream through 'result'.
42 :param input_stream: A stream containing subunit input.
43 :param result: A TestResult that will receive the test events.
44 :param passthrough_stream: All non-subunit input received will be
45 sent to this stream. If not provided, uses the ``TestProtocolServer``
46 default, which is ``sys.stdout``.
47 :param forward_stream: All subunit input received will be forwarded
48 to this stream. If not provided, uses the ``TestProtocolServer``
49 default, which is to not forward any input.
50 :return: True if the test run described by ``input_stream`` was
51 successful. False otherwise.
53 test = ProtocolTestCase(
54 input_stream, passthrough=passthrough_stream,
55 forward=forward_stream)
59 return result.wasSuccessful()
62 def filter_by_result(result_factory, output_path, no_passthrough, forward,
63 input_stream=sys.stdin):
64 """Filter an input stream using a test result.
66 :param result_factory: A callable that when passed an output stream
67 returns a TestResult. It is expected that this result will output
69 :param output_path: A path send output to. If None, output will be go
71 :param no_passthrough: If True, all non-subunit input will be discarded.
72 If False, that input will be sent to ``sys.stdout``.
73 :param forward: If True, all subunit input will be forwarded directly to
74 ``sys.stdout`` as well as to the ``TestResult``.
75 :param input_stream: The source of subunit input. Defaults to
77 :return: 0 if the input represents a successful test run, 1 if a failed
81 passthrough_stream = DiscardStream()
83 passthrough_stream = None
86 forward_stream = sys.stdout
90 if output_path is None:
91 output_to = sys.stdout
93 output_to = file(output_path, 'wb')
96 result = result_factory(output_to)
97 was_successful = run_tests_from_stream(
98 input_stream, result, passthrough_stream, forward_stream)
108 def run_filter_script(result_factory, description):
109 """Main function for simple subunit filter scripts.
111 Many subunit filter scripts take a stream of subunit input and use a
112 TestResult to handle the events generated by that stream. This function
113 wraps a lot of the boiler-plate around that by making a script with
114 options for handling passthrough information and stream forwarding, and
115 that will exit with a successful return code (i.e. 0) if the input stream
116 represents a successful test run.
118 :param result_factory: A callable that takes an output stream and returns
119 a test result that outputs to that stream.
120 :param description: A description of the filter script.
122 parser = make_options(description)
123 (options, args) = parser.parse_args()
126 result_factory, options.output_to, options.no_passthrough,