-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add --max-failures <n> option in test harness #25569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,7 +275,7 @@ def error_on_legacy_suite_names(args): | |
# order to run the tests in. Generally this is slowest-first to maximize | ||
# parallelization, but if running with fail-fast, then the tests with recent | ||
# known failure frequency are run first, followed by slowest first. | ||
def create_test_run_sorter(failfast): | ||
def create_test_run_sorter(sort_failing_tests_at_front): | ||
previous_test_run_results = common.load_previous_test_run_results() | ||
|
||
def read_approx_fail_freq(test_name): | ||
|
@@ -297,8 +297,8 @@ def sort_tests_failing_and_slowest_first_comparator(x, y): | |
y = str(y) | ||
|
||
# Look at the number of times this test has failed, and order by failures count first | ||
# Only do this in --failfast, if we are looking to fail early. (otherwise sorting by last test run duration is more productive) | ||
if failfast: | ||
# Only do this if we are looking to fail early. (otherwise sorting by last test run duration is more productive) | ||
if sort_failing_tests_at_front: | ||
x_fail_freq = read_approx_fail_freq(x) | ||
y_fail_freq = read_approx_fail_freq(y) | ||
if x_fail_freq != y_fail_freq: | ||
|
@@ -370,7 +370,7 @@ def load_test_suites(args, modules, options): | |
tests = flattened_tests(loaded_tests) | ||
suite = suite_for_module(m, tests, options) | ||
if options.failing_and_slow_first: | ||
tests = sorted(tests, key=cmp_to_key(create_test_run_sorter(options.failfast))) | ||
tests = sorted(tests, key=cmp_to_key(create_test_run_sorter(options.max_failures < len(tests) / 2))) | ||
for test in tests: | ||
if not found_start: | ||
# Skip over tests until we find the start | ||
|
@@ -480,7 +480,8 @@ def parse_args(): | |
parser.add_argument('--browser-auto-config', type=bool, default=True, | ||
help='Use the default CI browser configuration.') | ||
parser.add_argument('tests', nargs='*') | ||
parser.add_argument('--failfast', action='store_true') | ||
parser.add_argument('--failfast', action='store_true', help='If true, test run will abort on first failed test.') | ||
parser.add_argument('--max-failures', type=int, default=2**31 - 1, help='If specified, test run will abort after N failed tests.') | ||
parser.add_argument('--failing-and-slow-first', action='store_true', help='Run failing tests first, then sorted by slowest first. Combine with --failfast for fast fail-early CI runs.') | ||
parser.add_argument('--start-at', metavar='NAME', help='Skip all tests up until <NAME>') | ||
parser.add_argument('--continue', dest='_continue', action='store_true', | ||
|
@@ -492,7 +493,15 @@ def parse_args(): | |
parser.add_argument('--repeat', type=int, default=1, | ||
help='Repeat each test N times (default: 1).') | ||
parser.add_argument('--bell', action='store_true', help='Play a sound after the test suite finishes.') | ||
return parser.parse_args() | ||
|
||
options = parser.parse_args() | ||
|
||
if options.failfast: | ||
if options.max_failures != 0: | ||
utils.exit_with_error('--failfast and --max-failures are mutually exclusive!') | ||
juj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
options.max_failures = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took a convention of max_failures to mean "maximum allowed failures before aborting the test run". So max_failures = 0 means that zero failures are allowed, after that test run is aborted. (first failure will abort) |
||
|
||
return options | ||
|
||
|
||
def configure(): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I wonder if you can you do something
action=store_constant
+target=max_failures
here? Maybe too clever.lgtm either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm there are still a couple of uses of the
options.failfast
variable that this PR does not change, so keeping that around for now helps.