feat: 자동 부트스트랩 기능 추가 및 인벤토리 검사 개선
- `stone-furnace` 배치 후 자동으로 `coal`과 `iron-ore`/`copper-ore`를 투입하여 제련이 시작되도록 보정하는 기능 추가 - `insert_to_entity` 호출 전에 `can_insert` 여부를 확인하여 아이템 증발 위험을 줄이는 로직 개선 - `README.md`에 새로운 기능 설명 추가 - `tests/test_furnace_bootstrap.py` 및 `tests/test_insert_to_entity.py`에 대한 단위 테스트 추가
This commit is contained in:
91
tests/test_furnace_bootstrap.py
Normal file
91
tests/test_furnace_bootstrap.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import unittest
|
||||
|
||||
|
||||
from action_executor import ActionExecutor
|
||||
|
||||
|
||||
class _FakeRCON:
|
||||
pass
|
||||
|
||||
|
||||
class TestFurnaceBootstrap(unittest.TestCase):
|
||||
def test_auto_bootstrap_calls_insert_in_expected_order(self):
|
||||
"""
|
||||
stone-furnace 배치 직후:
|
||||
- 먼저 coal(연료)을 넣고
|
||||
- 그 다음 ore(iron-ore 우선)을 넣어 제련이 시작되어야 한다.
|
||||
"""
|
||||
ex = ActionExecutor(_FakeRCON())
|
||||
|
||||
def fake_get_item_count(item: str) -> int:
|
||||
return {
|
||||
"coal": 20,
|
||||
"iron-ore": 50,
|
||||
"copper-ore": 0,
|
||||
}.get(item, 0)
|
||||
|
||||
ex._get_item_count = fake_get_item_count # type: ignore[attr-defined]
|
||||
|
||||
calls: list[tuple[int, int, str, int]] = []
|
||||
|
||||
def fake_insert(x: int, y: int, item: str = "coal", count: int = 50):
|
||||
calls.append((x, y, item, count))
|
||||
return True, "OK"
|
||||
|
||||
ex.insert_to_entity = fake_insert # type: ignore[assignment]
|
||||
|
||||
# NOTE: 아직 구현 전이므로 이 테스트는 현재 실패해야 한다(TDD RED).
|
||||
ex._auto_bootstrap_furnace(
|
||||
furnace_name="stone-furnace",
|
||||
x=-91,
|
||||
y=-68,
|
||||
reason="iron-ore(50) 제련 시작",
|
||||
)
|
||||
|
||||
self.assertEqual(calls[0][2], "coal")
|
||||
self.assertEqual(calls[0][3], 20) # min(50, coal=20)
|
||||
|
||||
self.assertEqual(calls[1][2], "iron-ore")
|
||||
self.assertEqual(calls[1][3], 50) # min(50, iron-ore=50)
|
||||
self.assertEqual(len(calls), 2)
|
||||
|
||||
def test_execute_triggers_bootstrap_after_successful_place_entity(self):
|
||||
ex = ActionExecutor(_FakeRCON())
|
||||
|
||||
# place_entity를 성공으로 고정(좌표는 message에서 파싱한다고 가정)
|
||||
def fake_place_entity(name: str, x: int, y: int, direction: str = "north"):
|
||||
return True, "stone-furnace 배치 (-91, -68)"
|
||||
|
||||
ex.place_entity = fake_place_entity # type: ignore[assignment]
|
||||
|
||||
called: list[dict] = []
|
||||
|
||||
def fake_auto_bootstrap(*, furnace_name: str, x: int, y: int, reason: str = ""):
|
||||
called.append({
|
||||
"furnace_name": furnace_name,
|
||||
"x": x,
|
||||
"y": y,
|
||||
"reason": reason,
|
||||
})
|
||||
return True, "mock_bootstrap_ok"
|
||||
|
||||
# NOTE: 아직 구현 전이므로 이 테스트는 현재 실패해야 한다(TDD RED).
|
||||
ex._auto_bootstrap_furnace = fake_auto_bootstrap # type: ignore[attr-defined]
|
||||
|
||||
ok, msg = ex.execute({
|
||||
"action": "place_entity",
|
||||
"reason": "현재 인벤토리에 iron-ore(50)가 있어 제련 시작",
|
||||
"params": {
|
||||
"name": "stone-furnace",
|
||||
"x": -91,
|
||||
"y": -68,
|
||||
"direction": "north",
|
||||
},
|
||||
})
|
||||
|
||||
self.assertTrue(ok, msg)
|
||||
self.assertEqual(len(called), 1)
|
||||
self.assertEqual(called[0]["furnace_name"], "stone-furnace")
|
||||
self.assertEqual(called[0]["x"], -91)
|
||||
self.assertEqual(called[0]["y"], -68)
|
||||
|
||||
Reference in New Issue
Block a user