The suite was reporting 331/331 while at least 82 of those tests asserted
nothing at all.
They raised during setup on APIs removed long ago -- add_layer(name=...),
GridPoint.color, mcrfpy.Animation(), entity.gridstate, mcrfpy.setScene,
assets/kenney_ice.png, GridData.compute_astar -- registered no timers, hit the
engine's auto-exit-when-no-timers path, exited 0, and were scored PASS. Their
assertions had not executed in months. test_metrics.py is the sharpest example:
the existing metrics test died on line 140 with a TypeError, which is precisely
why #341 (get_metrics counters reading 0) went unnoticed.
The engine no longer permits this (#350: a headless --exec script must call
sys.exit()), and run_tests.py no longer passes a test whose output contains a
Traceback. This commit repairs the 82 they exposed, migrating each to the
current API while preserving its original intent -- not deleting assertions to
make the command exit 0. Each repair was adversarially re-verified by a second
pass asking "is this still a test, or was it gutted?"; none were.
Two tests could not be made to pass because they were right and the engine was
wrong. Rather than paper over them they were left failing and the bugs fixed
separately in 48eef0b: DijkstraMap path order (#375) and layer-setter cache
invalidation (#376). Three integration tests had encoded the reversed Dijkstra
order as expected behavior; their assertions now state the real contract
(excludes the origin, ends at the root).
Suite: 334/334, every one of them actually asserting.
Refs #341, #350, #372
200 lines
6.3 KiB
Python
200 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Regression test for issue #147: Dynamic Layer System for Grid
|
|
|
|
Tests:
|
|
1. ColorLayer creation and manipulation
|
|
2. TileLayer creation and manipulation
|
|
3. Layer z_index ordering relative to entities
|
|
4. Layer management (add_layer, remove_layer, layers property)
|
|
|
|
API notes (current contract):
|
|
- Layers are constructed standalone (TileLayer/ColorLayer ctors take kwargs) and then
|
|
attached with grid_data.add_layer(layer) -- add_layer takes an object, not kwargs.
|
|
- Layer management (add_layer / remove_layer / layer) lives on GridData
|
|
(grid.grid_data); the Grid view exposes the read-only `layers` tuple.
|
|
- Layers are looked up BY NAME, not by z_index (grid_data.layer(name)).
|
|
"""
|
|
import mcrfpy
|
|
import sys
|
|
|
|
print("=" * 60)
|
|
print("Issue #147 Regression Test: Dynamic Layer System for Grid")
|
|
print("=" * 60)
|
|
|
|
# Create test scene
|
|
test = mcrfpy.Scene("test")
|
|
mcrfpy.current_scene = test
|
|
ui = test.children
|
|
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
|
|
|
# Create grid with explicit empty layers (#150 migration)
|
|
grid = mcrfpy.Grid(pos=(50, 50), size=(400, 300), grid_size=(20, 15), texture=texture, layers=[])
|
|
ui.append(grid)
|
|
grid_data = grid.grid_data
|
|
|
|
print("\n--- Test 1: Initial state (no layers) ---")
|
|
if len(grid.layers) == 0:
|
|
print(" PASS: Grid starts with no layers (layers=[])")
|
|
else:
|
|
print(f" FAIL: Expected 0 layers, got {len(grid.layers)}")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 2: Add ColorLayer ---")
|
|
color_layer = grid_data.add_layer(mcrfpy.ColorLayer(name="color", z_index=-1))
|
|
print(f" Created: {color_layer}")
|
|
if color_layer is not None:
|
|
print(" PASS: ColorLayer created")
|
|
else:
|
|
print(" FAIL: ColorLayer creation returned None")
|
|
sys.exit(1)
|
|
|
|
# Test ColorLayer properties
|
|
if color_layer.z_index == -1:
|
|
print(" PASS: ColorLayer z_index is -1")
|
|
else:
|
|
print(f" FAIL: Expected z_index -1, got {color_layer.z_index}")
|
|
sys.exit(1)
|
|
|
|
if color_layer.visible:
|
|
print(" PASS: ColorLayer is visible by default")
|
|
else:
|
|
print(" FAIL: ColorLayer should be visible by default")
|
|
sys.exit(1)
|
|
|
|
grid_size = color_layer.grid_size
|
|
if grid_size == (20, 15):
|
|
print(f" PASS: ColorLayer grid_size is {grid_size}")
|
|
else:
|
|
print(f" FAIL: Expected (20, 15), got {grid_size}")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 3: ColorLayer cell access ---")
|
|
# Set a color
|
|
color_layer.set((5, 5), mcrfpy.Color(255, 0, 0, 128))
|
|
color = color_layer.at(5, 5)
|
|
if color.r == 255 and color.g == 0 and color.b == 0 and color.a == 128:
|
|
print(f" PASS: Color at (5,5) is {color.r}, {color.g}, {color.b}, {color.a}")
|
|
else:
|
|
print(f" FAIL: Color mismatch")
|
|
sys.exit(1)
|
|
|
|
# Fill entire layer
|
|
color_layer.fill(mcrfpy.Color(0, 0, 255, 64))
|
|
color = color_layer.at(0, 0)
|
|
if color.b == 255 and color.a == 64:
|
|
print(" PASS: ColorLayer fill works")
|
|
else:
|
|
print(" FAIL: ColorLayer fill did not work")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 4: Add TileLayer ---")
|
|
tile_layer = grid_data.add_layer(mcrfpy.TileLayer(name="tile", z_index=-2, texture=texture))
|
|
print(f" Created: {tile_layer}")
|
|
if tile_layer is not None:
|
|
print(" PASS: TileLayer created")
|
|
else:
|
|
print(" FAIL: TileLayer creation returned None")
|
|
sys.exit(1)
|
|
|
|
if tile_layer.z_index == -2:
|
|
print(" PASS: TileLayer z_index is -2")
|
|
else:
|
|
print(f" FAIL: Expected z_index -2, got {tile_layer.z_index}")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 5: TileLayer cell access ---")
|
|
# Set a tile
|
|
tile_layer.set((3, 3), 42)
|
|
tile = tile_layer.at(3, 3)
|
|
if tile == 42:
|
|
print(f" PASS: Tile at (3,3) is {tile}")
|
|
else:
|
|
print(f" FAIL: Expected 42, got {tile}")
|
|
sys.exit(1)
|
|
|
|
# Fill entire layer
|
|
tile_layer.fill(10)
|
|
tile = tile_layer.at(0, 0)
|
|
if tile == 10:
|
|
print(" PASS: TileLayer fill works")
|
|
else:
|
|
print(" FAIL: TileLayer fill did not work")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 6: Layer ordering ---")
|
|
layers = grid.layers
|
|
if len(layers) == 2:
|
|
print(f" PASS: Grid has 2 layers")
|
|
else:
|
|
print(f" FAIL: Expected 2 layers, got {len(layers)}")
|
|
sys.exit(1)
|
|
|
|
# Layers should be sorted by z_index
|
|
if layers[0].z_index <= layers[1].z_index:
|
|
print(f" PASS: Layers sorted by z_index ({layers[0].z_index}, {layers[1].z_index})")
|
|
else:
|
|
print(f" FAIL: Layers not sorted")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 7: Get layer by name ---")
|
|
# Layer lookup is by NAME now (grid.layer(z_index) no longer exists); z_index is still
|
|
# the ordering key, verified in Test 6. Note: layer lookups return a fresh wrapper each
|
|
# call (layers are not in PythonObjectCache), so compare identity via the shared data,
|
|
# not `is`.
|
|
layer = grid_data.layer("color")
|
|
if layer is not None and layer.z_index == -1 and layer.at(5, 5).b == color_layer.at(5, 5).b:
|
|
print(" PASS: grid_data.layer('color') returns the ColorLayer")
|
|
else:
|
|
print(" FAIL: Could not get ColorLayer by name")
|
|
sys.exit(1)
|
|
|
|
layer = grid_data.layer("tile")
|
|
if layer is not None and layer.z_index == -2 and layer.at(3, 3) == tile_layer.at(3, 3):
|
|
print(" PASS: grid_data.layer('tile') returns the TileLayer")
|
|
else:
|
|
print(" FAIL: Could not get TileLayer by name")
|
|
sys.exit(1)
|
|
|
|
layer = grid_data.layer("nonexistent")
|
|
if layer is None:
|
|
print(" PASS: grid_data.layer('nonexistent') returns None for non-existent layer")
|
|
else:
|
|
print(" FAIL: Should return None for non-existent layer")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 8: Layer above entities (z_index >= 0) ---")
|
|
fog_layer = grid_data.add_layer(mcrfpy.ColorLayer(name="fog", z_index=1))
|
|
if fog_layer.z_index == 1:
|
|
print(" PASS: Created layer with z_index=1 (above entities)")
|
|
else:
|
|
print(" FAIL: Layer z_index incorrect")
|
|
sys.exit(1)
|
|
|
|
# Set fog
|
|
fog_layer.fill(mcrfpy.Color(0, 0, 0, 128))
|
|
print(" PASS: Fog layer filled")
|
|
|
|
print("\n--- Test 9: Remove layer ---")
|
|
initial_count = len(grid.layers)
|
|
grid_data.remove_layer(fog_layer)
|
|
final_count = len(grid.layers)
|
|
if final_count == initial_count - 1:
|
|
print(f" PASS: Layer removed ({initial_count} -> {final_count})")
|
|
else:
|
|
print(f" FAIL: Layer count didn't decrease ({initial_count} -> {final_count})")
|
|
sys.exit(1)
|
|
|
|
print("\n--- Test 10: Layer visibility toggle ---")
|
|
color_layer.visible = False
|
|
if not color_layer.visible:
|
|
print(" PASS: Layer visibility can be toggled")
|
|
else:
|
|
print(" FAIL: Layer visibility toggle failed")
|
|
sys.exit(1)
|
|
color_layer.visible = True
|
|
|
|
print("\n" + "=" * 60)
|
|
print("All tests PASSED")
|
|
print("=" * 60)
|
|
sys.exit(0)
|