From be63a1cbde079290de3ae365cac51563610dcc10 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Sat, 14 Feb 2026 00:33:07 -0500 Subject: [PATCH] Extract shared test fixtures to conftest.py Moved common test fixtures (mock_writer, mock_reader, test_zone, player, nearby_player, clear_state) from individual test files into a shared conftest.py. This eliminates duplication across test_power.py, test_sleep.py, test_combat_zaxis.py, test_quit.py, test_stamina_cues.py, and test_stamina_cue_wiring.py. Some test files override specific fixtures where they need custom behavior (e.g., test_quit.py adds a close method to mock_writer, stamina tests use smaller zones and custom player positions). --- tests/conftest.py | 69 ++++++++++++++++++++++++++++++++ tests/test_combat_zaxis.py | 55 ++----------------------- tests/test_power.py | 59 --------------------------- tests/test_quit.py | 45 +++------------------ tests/test_sleep.py | 58 --------------------------- tests/test_stamina_cue_wiring.py | 11 ++--- tests/test_stamina_cues.py | 12 ++---- 7 files changed, 84 insertions(+), 225 deletions(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..a91e30e --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,69 @@ +"""Shared test fixtures for mudlib tests.""" + +from unittest.mock import AsyncMock, MagicMock + +import pytest + +from mudlib.combat.engine import active_encounters +from mudlib.player import Player, players +from mudlib.zone import Zone + + +@pytest.fixture(autouse=True) +def clear_state(): + """Clear global state before and after each test.""" + players.clear() + active_encounters.clear() + yield + players.clear() + active_encounters.clear() + + +@pytest.fixture +def mock_writer(): + """Create a mock writer for testing.""" + writer = MagicMock() + writer.write = MagicMock() + writer.drain = AsyncMock() + return writer + + +@pytest.fixture +def mock_reader(): + """Create a mock reader for testing.""" + return MagicMock() + + +@pytest.fixture +def test_zone(): + """Create a test zone for players.""" + terrain = [["." for _ in range(256)] for _ in range(256)] + zone = Zone( + name="testzone", + width=256, + height=256, + toroidal=True, + terrain=terrain, + impassable=set(), + ) + return zone + + +@pytest.fixture +def player(mock_reader, mock_writer, test_zone): + """Create a test player named Goku at origin.""" + p = Player(name="Goku", x=0, y=0, reader=mock_reader, writer=mock_writer) + p.location = test_zone + test_zone._contents.append(p) + players[p.name] = p + return p + + +@pytest.fixture +def nearby_player(mock_reader, mock_writer, test_zone): + """Create a nearby test player named Vegeta at origin.""" + p = Player(name="Vegeta", x=0, y=0, reader=mock_reader, writer=mock_writer) + p.location = test_zone + test_zone._contents.append(p) + players[p.name] = p + return p diff --git a/tests/test_combat_zaxis.py b/tests/test_combat_zaxis.py index bfe8534..18617f8 100644 --- a/tests/test_combat_zaxis.py +++ b/tests/test_combat_zaxis.py @@ -1,67 +1,20 @@ """Tests for z-axis altitude checks in combat.""" from pathlib import Path -from unittest.mock import AsyncMock, MagicMock import pytest from mudlib.combat import commands as combat_commands from mudlib.combat.encounter import CombatState -from mudlib.combat.engine import active_encounters, get_encounter, start_encounter +from mudlib.combat.engine import get_encounter, start_encounter from mudlib.combat.moves import load_moves -from mudlib.player import Player, players -from mudlib.zone import Zone - - -@pytest.fixture(autouse=True) -def clear_state(): - """Clear encounters and players before and after each test.""" - active_encounters.clear() - players.clear() - yield - active_encounters.clear() - players.clear() - - -@pytest.fixture -def test_zone(): - """Create a test zone for players.""" - terrain = [["." for _ in range(256)] for _ in range(256)] - zone = Zone( - name="testzone", - width=256, - height=256, - toroidal=True, - terrain=terrain, - impassable=set(), - ) - return zone - - -@pytest.fixture -def mock_writer(): - writer = MagicMock() - writer.write = MagicMock() - writer.drain = AsyncMock() - return writer - - -@pytest.fixture -def mock_reader(): - return MagicMock() - - -@pytest.fixture -def player(mock_reader, mock_writer, test_zone): - p = Player(name="Goku", x=0, y=0, reader=mock_reader, writer=mock_writer) - p.location = test_zone - test_zone._contents.append(p) - players[p.name] = p - return p @pytest.fixture def target(mock_reader, mock_writer, test_zone): + """Alias for nearby_player fixture with name 'target' for this module.""" + from mudlib.player import Player, players + t = Player(name="Vegeta", x=0, y=0, reader=mock_reader, writer=mock_writer) t.location = test_zone test_zone._contents.append(t) diff --git a/tests/test_power.py b/tests/test_power.py index 133bf39..34f6575 100644 --- a/tests/test_power.py +++ b/tests/test_power.py @@ -2,71 +2,12 @@ import asyncio import time -from unittest.mock import AsyncMock, MagicMock import pytest from mudlib.combat.encounter import CombatEncounter from mudlib.combat.engine import active_encounters from mudlib.commands.power import cmd_power -from mudlib.player import Player, players -from mudlib.zone import Zone - - -@pytest.fixture(autouse=True) -def clear_state(): - """Clear players and encounters before and after each test.""" - players.clear() - active_encounters.clear() - yield - players.clear() - active_encounters.clear() - - -@pytest.fixture -def test_zone(): - """Create a test zone for players.""" - terrain = [["." for _ in range(256)] for _ in range(256)] - zone = Zone( - name="testzone", - width=256, - height=256, - toroidal=True, - terrain=terrain, - impassable=set(), - ) - return zone - - -@pytest.fixture -def mock_writer(): - writer = MagicMock() - writer.write = MagicMock() - writer.drain = AsyncMock() - return writer - - -@pytest.fixture -def mock_reader(): - return MagicMock() - - -@pytest.fixture -def player(mock_reader, mock_writer, test_zone): - p = Player(name="Goku", x=0, y=0, reader=mock_reader, writer=mock_writer) - p.location = test_zone - test_zone._contents.append(p) - players[p.name] = p - return p - - -@pytest.fixture -def nearby_player(mock_reader, mock_writer, test_zone): - p = Player(name="Vegeta", x=0, y=0, reader=mock_reader, writer=mock_writer) - p.location = test_zone - test_zone._contents.append(p) - players[p.name] = p - return p @pytest.mark.asyncio diff --git a/tests/test_quit.py b/tests/test_quit.py index 6026c21..79c2b50 100644 --- a/tests/test_quit.py +++ b/tests/test_quit.py @@ -1,39 +1,18 @@ """Tests for quit command.""" -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock, patch import pytest from mudlib.commands.quit import cmd_quit -from mudlib.player import Player, players -from mudlib.zone import Zone - - -@pytest.fixture(autouse=True) -def clear_state(): - """Clear players before and after each test.""" - players.clear() - yield - players.clear() - - -@pytest.fixture -def test_zone(): - """Create a test zone for players.""" - terrain = [["." for _ in range(256)] for _ in range(256)] - zone = Zone( - name="testzone", - width=256, - height=256, - toroidal=True, - terrain=terrain, - impassable=set(), - ) - return zone +from mudlib.player import players @pytest.fixture def mock_writer(): + """Override conftest mock_writer to add close method for quit tests.""" + from unittest.mock import AsyncMock + writer = MagicMock() writer.write = MagicMock() writer.drain = AsyncMock() @@ -41,20 +20,6 @@ def mock_writer(): return writer -@pytest.fixture -def mock_reader(): - return MagicMock() - - -@pytest.fixture -def player(mock_reader, mock_writer, test_zone): - p = Player(name="Goku", x=0, y=0, reader=mock_reader, writer=mock_writer) - p.location = test_zone - test_zone._contents.append(p) - players[p.name] = p - return p - - @pytest.mark.asyncio async def test_quit_blocked_during_combat(player): """Test quit is blocked when player is in combat mode.""" diff --git a/tests/test_sleep.py b/tests/test_sleep.py index be7df67..1f31562 100644 --- a/tests/test_sleep.py +++ b/tests/test_sleep.py @@ -1,67 +1,9 @@ """Tests for sleep command.""" -from unittest.mock import AsyncMock, MagicMock - import pytest from mudlib.commands.sleep import cmd_sleep -from mudlib.player import Player, players from mudlib.resting import STAMINA_PER_TICK, process_resting -from mudlib.zone import Zone - - -@pytest.fixture(autouse=True) -def clear_state(): - """Clear players before and after each test.""" - players.clear() - yield - players.clear() - - -@pytest.fixture -def test_zone(): - """Create a test zone for players.""" - terrain = [["." for _ in range(256)] for _ in range(256)] - zone = Zone( - name="testzone", - width=256, - height=256, - toroidal=True, - terrain=terrain, - impassable=set(), - ) - return zone - - -@pytest.fixture -def mock_writer(): - writer = MagicMock() - writer.write = MagicMock() - writer.drain = AsyncMock() - return writer - - -@pytest.fixture -def mock_reader(): - return MagicMock() - - -@pytest.fixture -def player(mock_reader, mock_writer, test_zone): - p = Player(name="Goku", x=0, y=0, reader=mock_reader, writer=mock_writer) - p.location = test_zone - test_zone._contents.append(p) - players[p.name] = p - return p - - -@pytest.fixture -def nearby_player(mock_reader, mock_writer, test_zone): - p = Player(name="Vegeta", x=0, y=0, reader=mock_reader, writer=mock_writer) - p.location = test_zone - test_zone._contents.append(p) - players[p.name] = p - return p @pytest.mark.asyncio diff --git a/tests/test_stamina_cue_wiring.py b/tests/test_stamina_cue_wiring.py index a1a816a..2e51c4b 100644 --- a/tests/test_stamina_cue_wiring.py +++ b/tests/test_stamina_cue_wiring.py @@ -10,21 +10,15 @@ from mudlib.player import Player from mudlib.zone import Zone -@pytest.fixture -def mock_writer(): - writer = MagicMock() - writer.write = MagicMock() - writer.drain = AsyncMock() - return writer - - @pytest.fixture def test_zone(): + """Override conftest test_zone with smaller zone for stamina tests.""" return Zone(name="test", width=10, height=10) @pytest.fixture def player(mock_writer, test_zone): + """Override conftest player with custom position and stats for stamina tests.""" p = Player( name="Goku", x=5, @@ -40,6 +34,7 @@ def player(mock_writer, test_zone): @pytest.fixture def defender(test_zone): + """Defender fixture with custom position for stamina tests.""" w = MagicMock() w.write = MagicMock() w.drain = AsyncMock() diff --git a/tests/test_stamina_cues.py b/tests/test_stamina_cues.py index 0f721c4..d8bfd62 100644 --- a/tests/test_stamina_cues.py +++ b/tests/test_stamina_cues.py @@ -8,21 +8,15 @@ from mudlib.player import Player from mudlib.zone import Zone -@pytest.fixture -def mock_writer(): - writer = MagicMock() - writer.write = MagicMock() - writer.drain = AsyncMock() - return writer - - @pytest.fixture def test_zone(): + """Override conftest test_zone with smaller zone for stamina tests.""" return Zone(name="test", width=10, height=10) @pytest.fixture def player(mock_writer, test_zone): + """Override conftest player with custom position and stats for stamina tests.""" p = Player( name="Goku", x=5, @@ -38,7 +32,7 @@ def player(mock_writer, test_zone): @pytest.fixture def nearby_player(test_zone): - """A nearby player to receive broadcasts.""" + """Override conftest nearby_player with custom position for stamina tests.""" w = MagicMock() w.write = MagicMock() w.drain = AsyncMock()