Initial commit
This commit is contained in:
136
tests/conftest.py
Normal file
136
tests/conftest.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""Shared pytest fixtures + helpers for the Dying Phone engine tests.
|
||||
|
||||
Everything runs headless via SDL's dummy drivers, so no window is needed.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
os.environ.setdefault("SDL_VIDEODRIVER", "dummy")
|
||||
os.environ.setdefault("SDL_AUDIODRIVER", "dummy")
|
||||
|
||||
import pygame
|
||||
import pytest
|
||||
|
||||
from game import settings as S
|
||||
from game.level import Level
|
||||
from game.game import Game
|
||||
from game.player import InputState
|
||||
|
||||
DT = 1 / 60.0
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def _pygame():
|
||||
pygame.init()
|
||||
pygame.display.set_mode((64, 64)) # a display so convert_alpha() works
|
||||
yield
|
||||
pygame.quit()
|
||||
|
||||
|
||||
# --- level/game factories ----------------------------------------------------
|
||||
@pytest.fixture
|
||||
def make_level(tmp_path):
|
||||
n = [0]
|
||||
|
||||
def _make(yaml_text):
|
||||
n[0] += 1
|
||||
path = tmp_path / f"level_{n[0]}.yaml"
|
||||
path.write_text(yaml_text)
|
||||
return Level(str(path))
|
||||
|
||||
return _make
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def make_game(tmp_path):
|
||||
n = [0]
|
||||
|
||||
def _make(yaml_text, **kw):
|
||||
n[0] += 1
|
||||
path = tmp_path / f"game_{n[0]}.yaml"
|
||||
path.write_text(yaml_text)
|
||||
# nonexistent assets dir -> placeholder rectangles (deterministic)
|
||||
return Game([str(path)], str(tmp_path / "no_assets"), **kw)
|
||||
|
||||
return _make
|
||||
|
||||
|
||||
# --- run-loop helpers ---------------------------------------------------------
|
||||
def step(game, inp=None):
|
||||
"""Advance one frame, mirroring Game.run()'s per-state dispatch."""
|
||||
inp = inp or InputState()
|
||||
if game.state == "playing":
|
||||
game._update_play(DT, inp)
|
||||
elif game.state == "dying":
|
||||
game.death_timer -= DT
|
||||
if game.death_timer <= 0:
|
||||
game._respawn()
|
||||
elif game.state == "charging":
|
||||
game.charge_timer += DT
|
||||
if game.charge_timer >= S.CHARGE_TIME:
|
||||
game.state = "won_all" if game._final else "won_level"
|
||||
elif game.state == "fading":
|
||||
game._update_fade(DT)
|
||||
|
||||
|
||||
def run(game, frames, inp_fn=None):
|
||||
for i in range(frames):
|
||||
step(game, inp_fn(i) if inp_fn else None)
|
||||
|
||||
|
||||
def place(game, col, row):
|
||||
"""Put the player's feet at the bottom of cell (col,row), centred."""
|
||||
t = game.level.tile
|
||||
game.player.fx = float(col * t + (t - game.player.w) / 2)
|
||||
game.player.fy = float(row * t + (t - game.player.h))
|
||||
game.player.vx = game.player.vy = 0.0
|
||||
game.player._sync_rect()
|
||||
|
||||
|
||||
def hold(**flags):
|
||||
inp = InputState()
|
||||
for k, v in flags.items():
|
||||
setattr(inp, k, v)
|
||||
return inp
|
||||
|
||||
|
||||
# --- fakes for isolated trap unit tests --------------------------------------
|
||||
class FakeLevel:
|
||||
tile = 32
|
||||
debug = False
|
||||
width = 800
|
||||
height = 480
|
||||
|
||||
def cell_rect(self, c, r):
|
||||
return pygame.Rect(c * 32, r * 32, 32, 32)
|
||||
|
||||
|
||||
class FakePlayer:
|
||||
def __init__(self, rect):
|
||||
self.rect = rect
|
||||
self.w = rect.w
|
||||
self.h = rect.h
|
||||
self.fx = float(rect.x)
|
||||
self.fy = float(rect.y)
|
||||
self.vx = self.vy = 0.0
|
||||
|
||||
def _sync_rect(self):
|
||||
self.rect.x = round(self.fx)
|
||||
self.rect.y = round(self.fy)
|
||||
|
||||
|
||||
class FakeGame:
|
||||
def __init__(self, rect):
|
||||
self.player = FakePlayer(rect)
|
||||
|
||||
|
||||
def reversals(values):
|
||||
"""Count direction reversals in a numeric sequence (for jitter tests)."""
|
||||
rev, prev = 0, 0
|
||||
for i in range(1, len(values)):
|
||||
d = (values[i] > values[i - 1]) - (values[i] < values[i - 1])
|
||||
if d and prev and d != prev:
|
||||
rev += 1
|
||||
if d:
|
||||
prev = d
|
||||
return rev
|
||||
Reference in New Issue
Block a user