bpo-44282: Fix occasional test_incremental_editing failures on buildbots (GH-26491)

Signed-off-by: Tal Einat <532281+taleinat@users.noreply.github.com>
This commit is contained in:
Tal Einat 2021-06-03 02:53:41 +03:00 committed by GitHub
parent 320eaa7f42
commit adef445dc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 41 deletions

View file

@ -2,7 +2,7 @@
import functools
def run_in_tk_mainloop(test_method):
def run_in_tk_mainloop(delay=1):
"""Decorator for running a test method with a real Tk mainloop.
This starts a Tk mainloop before running the test, and stops it
@ -13,44 +13,50 @@ def run_in_tk_mainloop(test_method):
using "yield" to allow the mainloop to process events and "after"
callbacks, and then continue the test from that point.
The delay argument is passed into root.after(...) calls as the number
of ms to wait before passing execution back to the generator function.
This also assumes that the test class has a .root attribute,
which is a tkinter.Tk object.
For example (from test_sidebar.py):
@run_test_with_tk_mainloop
@run_test_with_tk_mainloop()
def test_single_empty_input(self):
self.do_input('\n')
yield
self.assert_sidebar_lines_end_with(['>>>', '>>>'])
"""
@functools.wraps(test_method)
def new_test_method(self):
test_generator = test_method(self)
root = self.root
# Exceptions raised by self.assert...() need to be raised
# outside of the after() callback in order for the test
# harness to capture them.
exception = None
def after_callback():
nonlocal exception
try:
next(test_generator)
except StopIteration:
root.quit()
except Exception as exc:
exception = exc
root.quit()
else:
# Schedule the Tk mainloop to call this function again,
# using a robust method of ensuring that it gets a
# chance to process queued events before doing so.
# See: https://stackoverflow.com/q/18499082#comment65004099_38817470
root.after(1, root.after_idle, after_callback)
root.after(0, root.after_idle, after_callback)
root.mainloop()
def decorator(test_method):
@functools.wraps(test_method)
def new_test_method(self):
test_generator = test_method(self)
root = self.root
# Exceptions raised by self.assert...() need to be raised
# outside of the after() callback in order for the test
# harness to capture them.
exception = None
def after_callback():
nonlocal exception
try:
next(test_generator)
except StopIteration:
root.quit()
except Exception as exc:
exception = exc
root.quit()
else:
# Schedule the Tk mainloop to call this function again,
# using a robust method of ensuring that it gets a
# chance to process queued events before doing so.
# See: https://stackoverflow.com/q/18499082#comment65004099_38817470
root.after(delay, root.after_idle, after_callback)
root.after(0, root.after_idle, after_callback)
root.mainloop()
if exception:
raise exception
if exception:
raise exception
return new_test_method
return new_test_method
return decorator