Files
Aislo/resources/tester/test_b09_save_speed.py
T
eomsangdonandClaude Opus 5.5 3bd3bcc5a8 perf(B09 [저장] · 708-1): 같은 입력 되풀이 셈 묶음 — 화면 [저장] 3.7 s → 1.7 s · 결과 바이트 같음
- M01 캐시 `steady()` 범위 — 요청 한 번 안 파일 자국 한 번(77 번 × 19 ms → 1 번) · stale · forget 뒤 다시 · 범위 밖 그대로
- 두 번 셈(183-1) 2차 산근 = 1차가 본 단가(있음 · 값)가 같을 때만 1차 풀이 사본 · 다르면 다시 셈
- [저장] 단가 수요 한 번(셈 답에 넘김) · 단계 표시 = 셈과 함께
- B08 `once()` 범위 — B09 원천 읽기 때 토공 채집석 공제가 자재 집계표 답을 다시 씀(두 번 셈 → 한 번)
- 시험: test_b09_save_speed 새로 · test_183 바꿔 끼운 셈 함수 = 새 memo 인자 받음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 19:34:44 +09:00

92 lines
3.3 KiB
Python

"""B09 [저장] 속도 — 같은 결과 범위 안 다시 셈 줄임 지킴.
- 산근 두 번 셈(183-1) = 1차가 본 단가(있음 · 값)가 같을 때만 1차 풀이 그대로(`_Prices.same`)
- M01 `steady()` 범위 = 파일 자국 한 번 · `stale` 뒤 다시 셈 · 범위 밖은 늘 셈
- B08 `once()` 범위 = 채집석 공제가 자재 집계표 답을 다시 씀(셈 한 번)
"""
from __future__ import annotations
import asyncio
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity import B08_Quantity_Router_Material as material # noqa: E402
from B09_Estimation.B09_Estimation_Sangeun import _Prices # noqa: E402
from M01_MasterData import M01_MasterData_Store_Cache as cache # noqa: E402
SHEETS = {
"labor": [{"key": "L1", "price": 100}, {"key": "L2", "price": 5}],
"compare": [{"key": "M1", "applied": 3}],
"machine": [{"key": "E1", "labor": 1, "material": 2, "expense": 3}],
}
def _seen() -> _Prices:
got = _Prices(SHEETS)
got.labor.get("L1")
assert "M9" not in got.material
got.machine.get("E1")
return got
def test_산근_같은_단가면_다시_씀() -> None:
other = {**SHEETS, "labor": [{"key": "L1", "price": 100}, {"key": "L2", "price": 999}]}
assert _seen().same(_Prices({**other, "compare": []})) # 안 본 L2 · M1 은 안 셈
def test_산근_본_단가_바뀌면_다시_셈() -> None:
assert not _seen().same(_Prices({**SHEETS, "labor": [{"key": "L1", "price": 101}]}))
added = {**SHEETS, "compare": [{"key": "M9", "applied": 1}]}
assert not _seen().same(_Prices(added)) # 없던 자재가 생김
machine = {**SHEETS, "machine": [{"key": "E1", "labor": 1, "material": 2, "expense": 4}]}
assert not _seen().same(_Prices(machine))
def test_M01_범위_안_자국_한_번(monkeypatch) -> None:
calls = []
monkeypatch.setattr(cache, "_stamps", lambda folder: calls.append(folder) or {})
folder = Path("x")
cache._now(folder)
cache._now(folder)
assert len(calls) == 2 # 범위 밖 = 늘 셈
with cache.steady():
cache._now(folder)
cache._now(folder)
assert len(calls) == 3
cache.stale([]) # 스스로 고친 자리 = 다시 셈
cache._now(folder)
assert len(calls) == 4
cache._now(folder)
assert len(calls) == 5
def test_B08_범위_안_자재_집계표_한_번(monkeypatch, tmp_path) -> None:
calls = []
rows = [{"key": material.DEDUCT_KEY, "amount": 12.5}]
async def sheets(_pid, _root, _over):
calls.append(1)
return {"sheets": {"material": {"rows": rows}}}
async def root(_pid):
return tmp_path
monkeypatch.setattr(material, "_sheets", sheets)
monkeypatch.setattr(material, "_project_root", root)
monkeypatch.setattr(material, "quantity_settings", lambda _root: {})
async def run() -> list:
out = [await material.picked_deduction("p", tmp_path)]
with material.once():
await material.material_sheets("p")
out.append(await material.picked_deduction("p", tmp_path))
out.append(await material.picked_deduction("p", tmp_path))
return out
assert asyncio.run(run()) == [12.5, 12.5, 12.5]
assert len(calls) == 3 # 범위 안 공제 = 셈 없음