Files
werkrevisor/tests/test_prompt_out.py
claude-code 5e67065587
werkator build succeeded after 00:08
werkator/werkrevisor-statistics build succeeded after 00:24
werkrevisor 0.30.2: a dry run writes the model prompt to a file (#65)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-09 17:50:21 +02:00

70 lines
3.6 KiB
Python

import contextlib
import dataclasses
import io
import json
import os
import tempfile
import unittest
from tests.fakes import HEAD, ROOT, FakeGitea, FakeModel, config, deps, diff_for, gitea_file, pr_ref
from werkrevisor.cli import execute, main
from werkrevisor.redact import Redactor
from werkrevisor.verdict import Verdict
def prompt_run(gitea, model, cfg):
path = os.path.join(tempfile.mkdtemp(prefix="werkrevisor-test-"), "prompt.json")
d = dataclasses.replace(deps(gitea, model), prompt_out=path)
outcome = execute(cfg, pr_ref(), d, Redactor(), publish=False)
with open(path, encoding="utf-8") as f:
return outcome, json.load(f), path
class PromptOutTest(unittest.TestCase):
def test_the_prompt_goes_to_the_file_instead_of_the_model(self):
"""Scenario#65.01"""
gitea = FakeGitea(files=[gitea_file("src/a.py")], diff=diff_for("src/a.py", added=["x"]))
model = FakeModel(prompt_files=["src/a.py"])
outcome, written, path = prompt_run(gitea, model, config(gate={"yellow_gate": "block"}))
self.assertEqual(model.calls, [])
self.assertEqual((written["system"], written["user"]), model.prompts[-1])
self.assertEqual(outcome.result.llm_status, "skipped (prompt written)")
reason = next(r for r in outcome.result.reasons if r.code == "prompt_out")
self.assertEqual((reason.text, reason.verdict), (f"model not called: the prompt is in {path}", Verdict.GREEN))
def test_the_file_holds_the_prompt_after_the_size_checks(self):
"""Scenario#65.02"""
text = "".join(f"line number {i} of the large file\n" for i in range(1, 701)).encode()
diff = diff_for("src/a.py", added=["x"]).replace("@@ -1,0 +1,1 @@", "@@ -350,0 +350,1 @@")
gitea = FakeGitea(files=[gitea_file("src/a.py")], diff=diff)
gitea.raw_files["src/a.py"] = text
model = FakeModel(prompt_files=["src/a.py"], prompt_words=50)
cfg = config(gate={"yellow_gate": "block"}, model={"max_context_tokens": 3000},
review={"full_files": True, "max_full_file_chars": 100000, "max_full_files_chars": 200000,
"excerpt_context_lines": 400})
outcome, written, _ = prompt_run(gitea, model, cfg)
self.assertGreater(len(model.prompts), 1)
self.assertIn("### Full file: 'src/a.py'", model.prompts[0][1])
self.assertEqual(written["user"], model.prompts[-1][1])
self.assertNotIn("line number 1 of the large file", written["user"])
self.assertIn("context_reduced", [r.code for r in outcome.result.reasons])
def test_only_a_dry_run_writes_the_prompt(self):
"""Scenario#65.03, Scenario#65.04"""
with open(os.path.join(ROOT, "config", "werkprobe.toml"), encoding="utf-8") as f:
toml = f.read()
environ = {"WERKREVISOR_CONFIG_TOML": toml, "GITEA_BOT_TOKEN": "gitea-token-123",
"OPENROUTER_API_KEY": "sk-or-v1-test", "TYPESAFE_API_KEY": "ts-test",
"WERKATOR_GITEA_BASE_URL": "https://git.example.org", "WERKATOR_GITEA_OWNER": "o",
"WERKATOR_GITEA_REPO": "r", "WERKATOR_PR_NUMBER": "1", "WERKATOR_PR_HEAD_SHA": HEAD}
for argv in (["--prompt-out", "p.json"], ["--prompt-out", "p.json", "--no-publish", "--no-llm"]):
with self.subTest(argv=argv):
err = io.StringIO()
with contextlib.redirect_stderr(err):
self.assertEqual(main(argv, environ), 30)
self.assertIn("--prompt-out needs --no-publish and no --no-llm", err.getvalue())
if __name__ == "__main__":
unittest.main()