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
119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Example of CORRECT test pattern using mcrfpy.step() for automation
|
|
Refactored from timer-based approach to synchronous step() pattern.
|
|
|
|
Note (#350/#341): step() is the simulation clock and never renders;
|
|
automation.screenshot() is what forces a render of the current scene.
|
|
"""
|
|
import mcrfpy
|
|
from mcrfpy import automation
|
|
from datetime import datetime
|
|
import os
|
|
import sys
|
|
|
|
failures = []
|
|
|
|
def check(condition, message):
|
|
if condition:
|
|
print(f" ok: {message}")
|
|
else:
|
|
print(f" FAIL: {message}")
|
|
failures.append(message)
|
|
|
|
# This code runs during --exec script execution
|
|
print("=== Setting Up Test Scene ===")
|
|
|
|
# Create scene with visible content
|
|
timer_test_scene = mcrfpy.Scene("timer_test_scene")
|
|
timer_test_scene.activate()
|
|
mcrfpy.step(0.01) # Initialize scene
|
|
|
|
ui = timer_test_scene.children
|
|
|
|
# Add a bright red frame that should be visible
|
|
frame = mcrfpy.Frame(pos=(100, 100), size=(400, 300),
|
|
fill_color=mcrfpy.Color(255, 0, 0), # Bright red
|
|
outline_color=mcrfpy.Color(255, 255, 255), # White outline
|
|
outline=5.0)
|
|
ui.append(frame)
|
|
|
|
# Add text
|
|
caption = mcrfpy.Caption(pos=(150, 150),
|
|
text="STEP TEST - SHOULD BE VISIBLE",
|
|
fill_color=mcrfpy.Color(255, 255, 255))
|
|
caption.font_size = 24
|
|
frame.children.append(caption)
|
|
|
|
# Add click handler to demonstrate interaction
|
|
# (#230) on_click receives (pos: Vector, button: MouseButton, action: InputState)
|
|
clicks_received = []
|
|
def frame_clicked(pos, button, action):
|
|
clicks_received.append((pos, button, action))
|
|
print(f"Frame clicked at ({pos.x}, {pos.y}) with button {button} ({action})")
|
|
|
|
frame.on_click = frame_clicked
|
|
|
|
print("Scene setup complete.")
|
|
|
|
# Step to render the scene
|
|
mcrfpy.step(0.1)
|
|
|
|
print("\n=== Automation Test Running ===")
|
|
|
|
# NOW we can take screenshots that will show content!
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
filename = f"WORKING_screenshot_{timestamp}.png"
|
|
|
|
# Take screenshot - this should now show our red frame
|
|
result = automation.screenshot(filename)
|
|
print(f"Screenshot taken: {filename} - Result: {result}")
|
|
check(result is True, "screenshot() reported success")
|
|
check(os.path.exists(filename), f"{filename} exists on disk")
|
|
# A blank 1024x768 PNG compresses to a few hundred bytes; real content is far bigger
|
|
check(os.path.getsize(filename) > 2000,
|
|
f"{filename} contains rendered content (size {os.path.getsize(filename)} > 2000)")
|
|
|
|
# Test clicking on the frame
|
|
automation.click((200, 200)) # Click in center of red frame
|
|
|
|
# Step to process the click
|
|
mcrfpy.step(0.1)
|
|
|
|
check(len(clicks_received) > 0, "frame.on_click fired for click inside the frame")
|
|
if clicks_received:
|
|
pos, button, action = clicks_received[0]
|
|
check((pos.x, pos.y) == (200.0, 200.0), "click reported the position it was sent to")
|
|
check(button == mcrfpy.MouseButton.LEFT, "click reported the LEFT button")
|
|
check(action == mcrfpy.InputState.PRESSED, "click reported the PRESSED state")
|
|
|
|
# Test keyboard input
|
|
automation.typewrite("Hello from step-based test!")
|
|
|
|
# Step to process keyboard input
|
|
mcrfpy.step(0.1)
|
|
|
|
# Take another screenshot to show any changes
|
|
filename2 = f"WORKING_screenshot_after_click_{timestamp}.png"
|
|
result2 = automation.screenshot(filename2)
|
|
print(f"Second screenshot: {filename2}")
|
|
check(result2 is True, "second screenshot() reported success")
|
|
check(os.path.exists(filename2), f"{filename2} exists on disk")
|
|
|
|
# Clean up the artifacts this test produced
|
|
for f in (filename, filename2):
|
|
if os.path.exists(f):
|
|
os.remove(f)
|
|
|
|
print("\nThis works because:")
|
|
print("1. mcrfpy.step() advances simulation synchronously")
|
|
print("2. automation.screenshot() forces a render of the active scene")
|
|
print("3. The RenderTexture contains actual rendered content")
|
|
|
|
if failures:
|
|
print(f"\nFAIL: {len(failures)} check(s) failed")
|
|
for f in failures:
|
|
print(f" - {f}")
|
|
sys.exit(1)
|
|
|
|
print("\nPASS")
|
|
sys.exit(0)
|