Python 如何从pytest注入pygame事件?
如何从pytest模块将事件注入正在运行的pygame 下面是pygame的一个最小示例,它在按下Python 如何从pytest注入pygame事件?,python,pygame,pytest,Python,Pygame,Pytest,如何从pytest模块将事件注入正在运行的pygame 下面是pygame的一个最小示例,它在按下J时绘制一个白色矩形,并在按下Ctrl-Q时退出游戏 #!/usr/bin/env python """minimal_pygame.py""" import pygame def minimal_pygame(testing: bool=False): pygame.init() game_window_sf = p
J
时绘制一个白色矩形,并在按下Ctrl-Q
时退出游戏
#!/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()
我想写一个pytest
模块来自动测试它。我有一个可以在运行pygame
时注入事件的方法。我读到,yield from
允许双向通信,所以我想我必须为pygame.events
实现某种钩子,从pytest
模块注入,但它不像我想的那么简单,所以我把它注释掉了。如果在游戏运行时取消对下的测试钩子的注释,pygame
甚至不会等待任何输入
以下是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)
Pygame可以对自定义用户事件做出反应,而不是按键或鼠标事件。这是一个工作代码,pytest
向pygame
发送一个用户事件,pygame
对此作出反应,并将响应发送回pytest
进行评估:
#!/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()
以下是测试代码:
#!/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")
但是,作为无状态单元测试而不是集成测试的工具,pytest
,它可以使pygame在获得第一个响应(teardown测试)后退出。无法在当前pygame会话中继续并执行更多测试和断言。(只要尝试复制测试代码的最后两行以重新发送事件,它就会失败。)Pytest不是将一系列指令注入pygame以使其达到先决条件,然后执行一系列测试的正确工具
这至少是我从pygame discord频道上听到的。对于自动化集成测试,他们建议使用BDD工具(或python)