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.
51 test = ProtocolTestCase(
52 input_stream, passthrough=passthrough_stream,
53 forward=forward_stream)
59 def filter_by_result(result_factory, output_path, passthrough, forward,
60 input_stream=sys.stdin):
61 """Filter an input stream using a test result.
63 :param result_factory: A callable that when passed an output stream
64 returns a TestResult. It is expected that this result will output
66 :param output_path: A path send output to. If None, output will be go
68 :param passthrough: If True, all non-subunit input will be sent to
69 ``sys.stdout``. If False, that input will be discarded.
70 :param forward: If True, all subunit input will be forwarded directly to
71 ``sys.stdout`` as well as to the ``TestResult``.
72 :param input_stream: The source of subunit input. Defaults to
74 :return: A test result with the resultts of the run.
77 passthrough_stream = sys.stdout
79 passthrough_stream = DiscardStream()
82 forward_stream = sys.stdout
84 forward_stream = DiscardStream()
86 if output_path is None:
87 output_to = sys.stdout
89 output_to = file(output_path, 'wb')
92 result = result_factory(output_to)
93 run_tests_from_stream(
94 input_stream, result, passthrough_stream, forward_stream)
101 def run_filter_script(result_factory, description, post_run_hook=None):
102 """Main function for simple subunit filter scripts.
104 Many subunit filter scripts take a stream of subunit input and use a
105 TestResult to handle the events generated by that stream. This function
106 wraps a lot of the boiler-plate around that by making a script with
107 options for handling passthrough information and stream forwarding, and
108 that will exit with a successful return code (i.e. 0) if the input stream
109 represents a successful test run.
111 :param result_factory: A callable that takes an output stream and returns
112 a test result that outputs to that stream.
113 :param description: A description of the filter script.
115 parser = make_options(description)
116 (options, args) = parser.parse_args()
117 result = filter_by_result(
118 result_factory, options.output_to, not options.no_passthrough,
121 post_run_hook(result)
122 if result.wasSuccessful():