#!/usr/bin/env python # subunit: extensions to python unittest to get test results from subprocesses. # Copyright (C) 2008 Robert Collins # (C) 2009 Martin Pool # # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause # license at the users choice. A copy of both licenses are available in the # project source as Apache-2.0 and BSD. You may not use this file except in # compliance with one of these two licences. # # Unless required by applicable law or agreed to in writing, software # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # license you chose for the specific language governing permissions and # limitations under that license. # """Filter a subunit stream to include/exclude tests. The default is to strip successful tests. Tests can be filtered by Python regular expressions with --with and --without, which match both the test name and the error text (if any). The result contains tests which match any of the --with expressions and none of the --without expressions. For case-insensitive matching prepend '(?i)'. Remember to quote shell metacharacters. """ from optparse import OptionParser import sys import unittest import re from subunit import ( DiscardStream, ProtocolTestCase, TestProtocolClient, ) from subunit.test_results import TestResultFilter parser = OptionParser(description=__doc__) parser.add_option("--error", action="store_false", help="include errors", default=False, dest="error") parser.add_option("-e", "--no-error", action="store_true", help="exclude errors", dest="error") parser.add_option("--failure", action="store_false", help="include failures", default=False, dest="failure") parser.add_option("-f", "--no-failure", action="store_true", help="include failures", dest="failure") parser.add_option("--no-passthrough", action="store_true", help="Hide all non subunit input.", default=False, dest="no_passthrough") parser.add_option("-s", "--success", action="store_false", help="include successes", dest="success") parser.add_option("--no-skip", action="store_true", help="exclude skips", dest="skip") parser.add_option("--no-success", action="store_true", help="exclude successes", default=True, dest="success") parser.add_option("-m", "--with", type=str, help="regexp to include (case-sensitive by default)", action="append", dest="with_regexps") parser.add_option("--without", type=str, help="regexp to exclude (case-sensitive by default)", action="append", dest="without_regexps") (options, args) = parser.parse_args() def _compile_re_from_list(l): return re.compile("|".join(l), re.MULTILINE) def _make_regexp_filter(with_regexps, without_regexps): """Make a callback that checks tests against regexps. with_regexps and without_regexps are each either a list of regexp strings, or None. """ with_re = with_regexps and _compile_re_from_list(with_regexps) without_re = without_regexps and _compile_re_from_list(without_regexps) def check_regexps(test, outcome, err, details): """Check if this test and error match the regexp filters.""" test_str = str(test) + outcome + str(err) + str(details) if with_re and not with_re.search(test_str): return False if without_re and without_re.search(test_str): return False return True return check_regexps regexp_filter = _make_regexp_filter(options.with_regexps, options.without_regexps) result = TestProtocolClient(sys.stdout) result = TestResultFilter(result, filter_error=options.error, filter_failure=options.failure, filter_success=options.success, filter_skip=options.skip, filter_predicate=regexp_filter) if options.no_passthrough: passthrough_stream = DiscardStream() else: passthrough_stream = None test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream) test.run(result) sys.exit(0)