mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			62 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			62 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Utilities for testing with Tkinter"""
 | |
| import functools
 | |
| 
 | |
| 
 | |
| 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
 | |
|     at the end. This is faster and more robust than the common
 | |
|     alternative method of calling .update() and/or .update_idletasks().
 | |
| 
 | |
|     Test methods using this must be written as generator functions,
 | |
|     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()
 | |
|     def test_single_empty_input(self):
 | |
|         self.do_input('\n')
 | |
|         yield
 | |
|         self.assert_sidebar_lines_end_with(['>>>', '>>>'])
 | |
|     """
 | |
|     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
 | |
| 
 | |
|         return new_test_method
 | |
| 
 | |
|     return decorator
 | 
