import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) import pytest from app.curator.schema import validate_response def _pick(nums, role="안정"): return {"numbers": nums, "risk_tag": role, "reason": "x"} def _make_payload(core, bonus, ext, pool): return { "core_picks": core, "bonus_picks": bonus, "extended_picks": ext, "pool_picks": pool, "tier_rationale": {"bonus": "a", "extended": "b", "pool": "c"}, "narrative": { "headline": "h", "summary_3lines": ["1", "2", "3"], "retrospective": "지난주 평균 1.8", }, "confidence": 70, } def test_valid_4tier(): pool = [[i, i+1, i+2, i+3, i+4, i+5] for i in range(1, 21)] cores = [_pick(pool[i]) for i in range(5)] bonus = [_pick(pool[i]) for i in range(5, 10)] ext = [_pick(pool[i]) for i in range(10, 15)] pl = [_pick(pool[i]) for i in range(15, 20)] out = validate_response(_make_payload(cores, bonus, ext, pl), pool) assert len(out.core_picks) == 5 assert out.narrative.retrospective.startswith("지난주") def test_duplicate_pick_rejected(): pool = [[i, i+1, i+2, i+3, i+4, i+5] for i in range(1, 21)] cores = [_pick(pool[0])] * 5 # 중복 bonus = [_pick(pool[i]) for i in range(5, 10)] ext = [_pick(pool[i]) for i in range(10, 15)] pl = [_pick(pool[i]) for i in range(15, 20)] with pytest.raises(ValueError, match="duplicate"): validate_response(_make_payload(cores, bonus, ext, pl), pool) def test_pick_not_in_candidates_rejected(): pool = [[i, i+1, i+2, i+3, i+4, i+5] for i in range(1, 21)] foreign = [40, 41, 42, 43, 44, 45] cores = [_pick(foreign)] + [_pick(pool[i]) for i in range(1, 5)] bonus = [_pick(pool[i]) for i in range(5, 10)] ext = [_pick(pool[i]) for i in range(10, 15)] pl = [_pick(pool[i]) for i in range(15, 20)] with pytest.raises(ValueError, match="not in candidates"): validate_response(_make_payload(cores, bonus, ext, pl), pool)