[copybara] Sync with mostrobotpy (#8820)

GitOrigin-RevId: f03f29e57af22a74b680873090028b9c9f5c8063
This commit is contained in:
PJ Reiniger
2026-04-26 11:25:15 -04:00
committed by GitHub
parent af7d68e993
commit e5980b46ef
16 changed files with 75 additions and 41 deletions

View File

@@ -2,7 +2,7 @@
build-backend = "hatchling.build"
requires = [
"semiwrap~=0.3.0",
"hatch-meson~=0.1.0",
"hatch-meson~=0.1.2",
"hatch-robotpy~=0.2.1",
"hatchling",
"robotpy-native-wpilib==0.0.0",

View File

@@ -90,7 +90,11 @@ class RobotTest:
pyproject_path = project_path / "pyproject.toml"
if pyproject_path.exists():
with open(pyproject_path, "rb") as fp:
d = tomllib.load(fp)
try:
d = tomllib.load(fp)
except tomllib.TOMLDecodeError as e:
print(f"ERROR: {pyproject_path}: {e}", file=sys.stderr)
return 1
try:
v = d["tool"]["robotpy"]["testing"]["isolated"]
@@ -98,9 +102,12 @@ class RobotTest:
pass
else:
if not isinstance(v, bool):
raise ValueError(
f"tool.robotpy.testing.isolated must be a boolean value (got {v})"
print(
f"ERROR: {pyproject_path}: tool.robotpy.testing.isolated "
f"must be a boolean value (got {v!r})",
file=sys.stderr,
)
return 1
isolated = v
@@ -162,7 +169,10 @@ class RobotTest:
break
else:
if not builtin:
print("ERROR: Cannot run robot tests, as test directory was not found!")
print(
"ERROR: Cannot run robot tests, as test directory was not found!",
file=sys.stderr,
)
retv = self._no_tests(main_file, project_path)
return 1
@@ -194,8 +204,11 @@ class RobotTest:
# requires pytest 2.8.x
if retv == 5:
print()
print("ERROR: a tests directory was found, but no tests were defined")
print(file=sys.stderr)
print(
"ERROR: a tests directory was found, but no tests were defined",
file=sys.stderr,
)
retv = self._no_tests(main_file, project_path, retv)
return retv

View File

@@ -18,11 +18,7 @@ def group_name(request):
def get_active_alerts(level: Alert.Level) -> T.List[str]:
return [
a.text
for a in AlertSim.getAll()
if a.level == level and a.isActive()
]
return [a.text for a in AlertSim.getAll() if a.level == level and a.isActive()]
def is_alert_active(text: str, level: Alert.Level):
@@ -144,6 +140,7 @@ def test_set_text_while_set(group_name):
assert not is_alert_active("BEFORE", Alert.Level.LOW)
assert is_alert_active("AFTER", Alert.Level.LOW)
def test_get_active(group_name):
with (
Alert(group_name, "A", Alert.Level.HIGH) as a,
@@ -154,10 +151,10 @@ def test_get_active(group_name):
a.set(True)
b.set(True)
c.set(False)
active = AlertSim.getActive()
allAlerts = AlertSim.getAll()
assert len(active) == 2
assert len(allAlerts) == 3
@@ -169,4 +166,4 @@ def test_get_active(group_name):
allAlerts = AlertSim.getAll()
assert len(active) == 1
assert len(allAlerts) == 3
assert active[0].text == "B"
assert active[0].text == "B"

View File

@@ -41,6 +41,7 @@ class MockRobot(OpModeRobot):
super().__init__()
self.driver_station_connected_count = 0
self.none_periodic_count = 0
self.periodic_count = 0
def driverStationConnected(self):
self.driver_station_connected_count += 1
@@ -48,6 +49,9 @@ class MockRobot(OpModeRobot):
def nonePeriodic(self):
self.none_periodic_count += 1
def robotPeriodic(self):
self.periodic_count += 1
@pytest.fixture(autouse=True)
def sim_timing_setup():
@@ -135,8 +139,8 @@ def test_remove_op_mode():
assert options[0].name == "OneArgOpMode"
@pytest.mark.xfail(reason="wpilib bug")
def test_none_periodic():
@pytest.fixture
def periodic_robot_test_fixture():
class MyMockRobot(MockRobot):
def __init__(self):
super().__init__()
@@ -146,14 +150,40 @@ def test_none_periodic():
robot = MyMockRobot()
robot_thread = threading.Thread(target=robot.startCompetition)
robot_thread.daemon = True # Make thread daemon so it doesn't block test exit
robot_thread.start()
yield robot
robot.endCompetition()
robot_thread.join()
# @pytest.mark.xfail(reason="wpilib bug")
def test_none_periodic(periodic_robot_test_fixture):
robot = periodic_robot_test_fixture
wsim.waitForProgramStart()
# Time step to get periodic calls on 20 ms robot loop
wsim.stepTiming(0.110)
assert robot.none_periodic_count == 2
assert robot.none_periodic_count == 5
robot.endCompetition()
robot_thread.join(timeout=1.0) # Add timeout to prevent hanging
def test_robot_periodic(periodic_robot_test_fixture):
kPeriod = 0.020 # 20 ms
robot = periodic_robot_test_fixture
wsim.waitForProgramStart()
# RobotPeriodic should be called regardless of state
assert robot.periodic_count == 0
# Time step to get periodic calls on 20 ms robot loop
wsim.stepTiming(kPeriod)
assert robot.periodic_count == 1
# Additional time steps should continue calling RobotPeriodic
wsim.stepTiming(kPeriod)
assert robot.periodic_count == 2