79일차 운영 데이터 기반 Ops Assistant: 실습 15개 · 강의(개요 30장 · 단계 문서 · 4단계 정리 · 05 바이브), 정답본 LAB-A · answers · VIBE-A · tops 포함

This commit is contained in:
mcchae committed 2026-11-03 20:54:35 +09:00
1 parent 9ce9aceba6
commit 6f0ecd59a9
156 files changed
+31640

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
"""R2 · R3 · R4 · R6 · R9 · R10 · R14: commands, --json unchanged, exit codes 0 · 1 · 2 · 4."""
import json
from conftest import DATA, load
from tops.cli import main
def test_status_red_exits_4(fake, capsys):
assert main(["status", "--n8n", fake.base]) == 4
assert "🔴 DLQ 3 (parked 2)" in capsys.readouterr().out
def test_status_json_is_the_n8n_answer(fake, capsys):
main(["status", "--n8n", fake.base, "--json"])
assert json.loads(capsys.readouterr().out) == load("facts.json")
def test_status_from_env(fake, monkeypatch, capsys):
monkeypatch.setenv("TOPS_N8N", fake.base)
assert main(["status", "--from", "2026-10-19", "--to", "2026-10-23"]) == 4
assert fake.calls[0][1] == {"from": "2026-10-19", "to": "2026-10-23"}
def test_status_without_source_is_usage(monkeypatch, capsys):
monkeypatch.delenv("TOPS_N8N", raising=False)
assert main(["status"]) == 2
assert "--n8n" in capsys.readouterr().err
def test_n8n_off_exits_1(down, capsys):
assert main(["status", "--n8n", down]) == 1
assert "cannot read" in capsys.readouterr().err
def test_bad_option_exits_2(capsys):
assert main(["status", "--nope"]) == 2
def test_ask_refused_action(fake, capsys):
assert main(["ask", "--n8n", fake.base, "DLQ 1번 다시 돌려 줘"]) == 0
out = capsys.readouterr().out
assert "refused (read_only)" in out and "읽기만" in out
def test_ask_llm_router_answer(fake, capsys):
main(["ask", "--n8n", fake.base, "이번 주에 AI 쓰는 데 얼마나 나갔어?"])
assert capsys.readouterr().out.startswith("[cost · llm] numbers ✔")
def test_brief_prints_markdown(fake, capsys):
main(["brief", "--n8n", fake.base])
assert "| DLQ | 🔴 | 3건 (parked 2) |" in capsys.readouterr().out
def test_eval_gate_pass_and_fail(fake, capsys, tmp_path):
assert main(["eval", "--n8n", fake.base, str(DATA / "ops-golden.json"), "--min-score", "0.8"]) == 0
assert "8/8 · score 1 · gate pass (min 0.8)" in capsys.readouterr().out
one = tmp_path / "one.json"
one.write_text(json.dumps({"cases": [{"question": "알림이 몇 건 와 있어?", "area": "cost"}]}, ensure_ascii=False))
assert main(["eval", "--n8n", fake.base, str(one)]) == 4
assert "✘ 알림이 몇 건 와 있어? · area alerts · area_ok" in capsys.readouterr().out
assert fake.calls[-1][1] == {"cases": [{"question": "알림이 몇 건 와 있어?", "area": "cost"}]}
def test_eval_empty_is_usage(fake, tmp_path, capsys):
empty = tmp_path / "empty.json"
empty.write_text('{"cases": []}')
assert main(["eval", "--n8n", fake.base, str(empty)]) == 2
def test_audit_lists_questions(fake, capsys):
main(["audit", "--api", fake.base])
out = capsys.readouterr().out
assert out.startswith("3 question(s)") and "refused read_only" in out and "answered" in out
def test_tools_never_fail(capsys):
assert main(["tools"]) == 0