Skip to content

Add test suite for memory reader, state builder, and pathfinding#1

Open
ch3ronsa wants to merge 1 commit intoNousResearch:mainfrom
ch3ronsa:tests/memory-reader-and-state-builder
Open

Add test suite for memory reader, state builder, and pathfinding#1
ch3ronsa wants to merge 1 commit intoNousResearch:mainfrom
ch3ronsa:tests/memory-reader-and-state-builder

Conversation

@ch3ronsa
Copy link

@ch3ronsa ch3ronsa commented Mar 5, 2026

Summary

Adds the first test suite for the project as mentioned in the README's contribution areas ("Tests for memory readers and state builders").

79 tests across 3 test files, all passing. No ROM or emulator required — tests use a mock emulator with a 64KB RAM buffer.

What's covered

test_memory_reader.py (36 tests)

  • Gen-1 encoding table: uppercase, lowercase, digits, space, terminator
  • Name tables: all 151 species present, common moves/items/maps, 8 badges
  • RedBlueMemoryReader (mock emulator):
    • read_player: name, rival, money (BCD), badges, position, facing
    • read_party: single Pokemon, empty party, corrupted count (cap at 6)
    • read_bag: items with quantities, empty bag, terminator handling
    • read_battle: not in battle, wild encounter with enemy data
    • read_dialog: inactive, active via text_box_id, active via joy_ignore bit
    • read_map_info: known map (Pallet Town), unknown map ID
    • read_flags: has_pokedex, has_oaks_parcel, pokedex counts
    • _decode_status: OK, poison, paralysis, sleep, multiple status

test_state_builder.py (19 tests)

  • build_game_state: all sections present, metadata with/without frame_count, error handling (RuntimeError, NotImplementedError), partial failure isolation
  • build_state_summary: player info, party, location, bag, battle (active/inactive), dialog, flags, error sections, empty state

test_pathfinding.py (24 tests)

  • manhattan: same point, horizontal, vertical, diagonal, negative coords
  • neighbors: no collision map (4 neighbors), collision blocking, direction correctness
  • find_path (A*): same start/goal, straight paths, diagonal, collision map routing, no path, max iterations, wall avoidance with path verification
  • directions_to_actions: conversion, empty list
  • navigate: walk actions, same position
  • path_length: reachable, unreachable, same position

Test plan

  • pytest tests/ -v — 79 passed in 0.52s
  • No external dependencies required (mock-based)
  • Compatible with existing pyproject.toml pytest config

79 tests covering:
- RedBlueMemoryReader: player, party, bag, battle, dialog, map,
  flags, status decoding, Gen-1 encoding table, name tables
- State builder: build_game_state sections, error handling,
  partial failures, build_state_summary output
- Pathfinding: A* search, collision maps, wall avoidance,
  manhattan distance, neighbors, navigate, path_length

All tests use mock emulator (no ROM required).
@ch3ronsa
Copy link
Author

ch3ronsa commented Mar 5, 2026

On ROM-based integration tests:

These tests are intentionally mock-based because Pokemon ROMs are copyrighted and can't be included in the repo or CI. The mock emulator simulates a 64KB RAM buffer with the same read_u8/read_u16/read_range interface as the real Emulator class, so the memory reader logic (address offsets, BCD decoding, Gen-1 text encoding, party struct parsing) is fully exercised.

That said, integration tests with a real ROM would be valuable for verifying end-to-end behavior. A possible approach:

ROM_PATH = Path(os.environ.get("POKEMON_ROM_PATH", ""))

@pytest.mark.skipif(not ROM_PATH.exists(), reason="ROM not available (set POKEMON_ROM_PATH)")
def test_real_emulator_reads_player():
    emu = PyBoyEmulator(str(ROM_PATH))
    reader = RedBlueMemoryReader(emu)
    # advance a few frames, then verify state reads don't crash
    ...

Users with a ROM could run: POKEMON_ROM_PATH=./red.gb pytest tests/ -v

Happy to add this as a follow-up if the project wants to support it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant