Question: How can one inject events into a running pygame from a pytest test module? The following is a minimal example of a pygame which draws a white rectangle when J is pressed and quits the game when Ctrl-Q is pressed. #!/usr/bin/env python """minimal_pygame.py""" import pygame def minimal_pygame(testing: bool=False): pygame.init() game_window_sf = pygame.display.set_mode( size=(400, 300), ) pygame.display.flip() game_running = True while game_running: # Main game loop: # the following hook to inject events from pytest does not work: # if testing: # test_input = (yield) # pygame.event.post(test_input) for event in pygame.event.get(): # React to closing the pygame window: if event.type == pygame.QUIT: game_running = False break # React to keypresses: if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: # distinguish between Q and Ctrl-Q mods = pygame.key.get_mods() # End main loop if Ctrl-Q was pressed if mods & pygame.KMOD_CTRL: game_running = False break # Draw a white square when key J is pressed: if event.key == pygame.K_j: filled_rect = game_window_sf.fill(pygame.Color("white"), pygame.Rect(50, 50, 50, 50)) pygame.display.update([filled_rect]) pygame.quit() if __name__ == "__main__": minimal_pygame()  I want to write a pytest module which would automatically test it. I have read that one can inject events into running pygame. Here I read that yield from allows a bidirectional communication, so I thought I must implement some sort of a hook for pygame.events being injected from the pytest module, but it is not as simple as I thought, so I commented it out. If I uncomment the test hook under while game_running, pygame does not even wait for any input. Here is the test module for pytest: #!/usr/bin/env python """test_minimal_pygame.py""" import pygame import minimal_pygame def pygame_wrapper(coro): yield from coro def test_minimal_pygame(): wrap = pygame_wrapper(minimal_pygame.minimal_pygame(testing=True)) wrap.send(None) # prime the coroutine test_press_j = pygame.event.Event(pygame.KEYDOWN, {"key": pygame.K_j}) for e in [test_press_j]: wrap.send(e) 

Answer: Pygame can react to custom user events, not keypress or mouse events. Here is a working code where pytest sends a userevent to pygame, pygame reacts to it and sends a response back to pytest for evaluation: #!/usr/bin/env python """minimal_pygame.py""" import pygame TESTEVENT = pygame.event.custom_type() def minimal_pygame(testing: bool=False): pygame.init() game_window_sf = pygame.display.set_mode( size=(400, 300), ) pygame.display.flip() game_running = True while game_running: # Hook for testing if testing: attr_dict = (yield) test_event = pygame.event.Event(TESTEVENT, attr_dict) pygame.event.post(test_event) # Main game loop: pygame.time.wait(1000) for event in pygame.event.get(): # React to closing the pygame window: if event.type == pygame.QUIT: game_running = False break # React to keypresses: if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: # distinguish between Q and Ctrl-Q mods = pygame.key.get_mods() # End main loop if Ctrl-Q was pressed if mods & pygame.KMOD_CTRL: game_running = False break # React to TESTEVENTS: if event.type == TESTEVENT: if event.instruction == "draw_rectangle": filled_rect = game_window_sf.fill(pygame.Color("white"), pygame.Rect(50, 50, 50, 50)) pygame.display.update([filled_rect]) pygame.time.wait(1000) if testing: # Yield the color value of the pixel at (50, 50) back to pytest yield game_window_sf.get_at((50, 50)) pygame.quit() if __name__ == "__main__": minimal_pygame()  Here's the test code: #!/usr/bin/env python """test_minimal_pygame.py""" import minimal_pygame import pygame def pygame_wrapper(coro): yield from coro def test_minimal_pygame(): wrap = pygame_wrapper(minimal_pygame.minimal_pygame(testing=True)) wrap.send(None) # prime the coroutine # Create a dictionary of attributes for the future TESTEVENT attr_dict = {"instruction": "draw_rectangle"} response = wrap.send(attr_dict) assert response == pygame.Color("white")  It works, However, pytest, being a tool for stateless unit tests rather than integration tests, makes the pygame quit after it gets the first response (teardown test). It is not possible to continue and do more tests and assertions in the current pygame session. (Just try to duplicate the last two lines of the test code to resend the event, it will fail.) Pytest is not the right tool to inject a series of instructions into pygame to bring it to a precondition and then perform a series of tests. That's at least what I heard from people on the pygame discord channel. For automated integration tests they suggest a BDD tool like Cucumber (or behave for python).