test: add golden render for all formats

This commit is contained in:
banteg
2025-12-29 18:28:59 +04:00
parent e57e4fd04a
commit 2950fe116d
3 changed files with 48 additions and 1 deletions
+43
View File
@@ -0,0 +1,43 @@
{"type":"error","message":"Failed to load optional config file ~/.codex/local.toml (ENOENT); continuing with defaults","code":"CONFIG_NOT_FOUND","fatal":false}
{"type":"thread.started","thread_id":"thread_01JHEM1P9M8Z7Y2YQJ4G6N2C3D","cli_version":"0.56.0","model":"gpt-5-codex","sandbox_mode":"workspace-write","cwd":"/home/user/project"}
{"type":"turn.started","turn_id":"turn_01JHEM1P9M8Z7Y2YQJ4G6N2C3E"}
{"type":"item.started","item":{"id":"item_0001","type":"todo_list","items":[{"text":"Inspect repo structure","completed":false},{"text":"Run tests","completed":false},{"text":"Fix failing tests","completed":false},{"text":"Summarize changes","completed":false}]}}
{"type":"item.updated","item":{"id":"item_0001","type":"todo_list","items":[{"text":"Inspect repo structure","completed":true},{"text":"Run tests","completed":false},{"text":"Fix failing tests","completed":false},{"text":"Summarize changes","completed":false}]}}
{"type":"item.completed","item":{"id":"item_0001","type":"todo_list","items":[{"text":"Inspect repo structure","completed":true},{"text":"Run tests","completed":true},{"text":"Fix failing tests","completed":true},{"text":"Summarize changes","completed":false}]}}
{"type":"item.started","item":{"id":"item_0002","type":"web_search","query":"python jsonlines parser handle unknown fields"}}
{"type":"item.completed","item":{"id":"item_0002","type":"web_search","query":"python jsonlines parser handle unknown fields"}}
{"type":"error","message":"Web search disabled by policy; returned cached results only","code":"WEB_SEARCH_POLICY","fatal":false}
{"type":"item.started","item":{"id":"item_0003","type":"mcp_tool_call","server":"github","tool":"search_issues","status":"in_progress"}}
{"type":"item.updated","item":{"id":"item_0003","type":"mcp_tool_call","server":"github","tool":"search_issues","status":"completed"}}
{"type":"item.completed","item":{"id":"item_0003","type":"mcp_tool_call","server":"github","tool":"search_issues","status":"completed"}}
{"type":"item.started","item":{"id":"item_0004","type":"command_execution","command":"pytest -q","aggregated_output":"","exit_code":null,"status":"in_progress"}}
{"type":"item.updated","item":{"id":"item_0004","type":"command_execution","command":"pytest -q","aggregated_output":"....F\n","exit_code":null,"status":"in_progress"}}
{"type":"item.updated","item":{"id":"item_0004","type":"command_execution","command":"pytest -q","aggregated_output":"....F....\nFAILURES\n_________________________________ test_beta __________________________________\nE AssertionError: expected 42, got 0\n","exit_code":null,"status":"in_progress"}}
{"type":"item.completed","item":{"id":"item_0004","type":"command_execution","command":"pytest -q","aggregated_output":"....F....\n\nFAILURES\n_________________________________ test_beta __________________________________\nE AssertionError: expected 42, got 0\n\n=========================== short test summary info ===========================\nFAILED tests/test_beta.py::test_beta - AssertionError: expected 42, got 0\n1 failed, 11 passed in 0.98s\n","exit_code":1,"status":"failed"}}
{"type":"item.completed","item":{"id":"item_0005","type":"file_change","changes":[{"path":"src/compute_answer.py","kind":"update"},{"path":"tests/test_beta.py","kind":"update"}],"status":"completed"}}
{"type":"item.started","item":{"id":"item_0006","type":"command_execution","command":"pytest -q","aggregated_output":"","status":"in_progress","exit_code":null}}
{"type":"item.updated","item":{"id":"item_0006","type":"command_execution","command":"pytest -q","aggregated_output":"............\n","status":"in_progress"}}
{"type":"item.completed","item":{"id":"item_0006","type":"command_execution","command":"pytest -q","aggregated_output":"............\n12 passed in 1.23s\n","status":"completed","exit_code":0}}
{"type":"item.started","item":{"id":"item_0007","type":"reasoning","text":"Root cause: compute_answer() returned 0. Updated logic to return 42 for the valid input path. Re-ran pytest to confirm all tests pass."}}
{"type":"item.completed","item":{"id":"item_0007","type":"reasoning","text":"Root cause: compute_answer() returned 0. Updated logic to return 42 for the valid input path. Re-ran pytest to confirm all tests pass."}}
{"type":"item.started","item":{"id":"item_0008","type":"agent_message","text":"I found the failing assertion in "}}
{"type":"item.updated","item":{"id":"item_0008","type":"agent_message","text":"I found the failing assertion in tests/test_beta.py and updated src/compute_answer.py to return the expected value."}}
{"type":"item.completed","item":{"id":"item_0008","type":"agent_message","text":"I found the failing assertion in tests/test_beta.py and updated src/compute_answer.py to return the expected value (42). After the change, `pytest -q` reports 12 passed."}}
{"type":"turn.completed","usage":{"input_tokens":1840,"cached_input_tokens":256,"output_tokens":732},"latency_ms":8421}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"item_0009","type":"command_execution","command":"npm test","aggregated_output":"","exit_code":null,"status":"in_progress"}}
{"type":"item.completed","item":{"id":"item_0009","type":"command_execution","command":"npm test","aggregated_output":"sh: npm: command not found\n","exit_code":127,"status":"failed"}}
{"type":"item.completed","item":{"id":"item_0010","type":"error","message":"Command `npm` not found in PATH (exit 127)."}}
{"type":"turn.failed","error":{"message":"Aborted: required dependency `npm` is missing; cannot continue."},"exit_code":1}
{"type":"error","message":"codex exec exited non-zero (1) after turn.failed"}
{"type":"thread.started","thread_id":"thread_legacy_7f9c2d3e"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"item_l_0001","type":"agent_message","item_type":"assistant_message","text":"Legacy schema example: hello (item_type=assistant_message)."}}
{"type":"item.completed","item":{"id":"item_l_0002","item_type":"command_execution","command":"echo legacy","output":"legacy\n","exit_code":0,"status":"completed"}}
{"type":"turn.completed","usage":{"input_tokens":12,"output_tokens":9}}
{"type":"thread.started","thread_id":"thread_future_01JK0Y6F8K6C7R3N1MGZ9G9A2B"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"item_f_0001","type":"tool_call","name":"my_custom_tool","arguments":{"foo":"bar","n":3},"status":"completed","result":{"ok":true}}}
{"type":"item.completed","item":{"id":"item_f_0002","type":"file_change","changes":[{"path":"README.md","kind":"add"}],"status":"failed","error":"permission denied"}}
{"type":"turn.rate_limited","retry_after_ms":1200}
{"type":"turn.completed","usage":null}
+32
View File
@@ -0,0 +1,32 @@
stream error: Failed to load optional config file ~/.codex/local.toml (ENOENT); continuing with defaults
thread started
turn started
2. ✓ searched: python jsonlines parser handle unknown fields
stream error: Web search disabled by policy; returned cached results only
3. ▸ tool: github.search_issues
3. ✓ tool: github.search_issues
4. ▸ `pytest -q`
4. ✗ `pytest -q` (exit 1)
5. ✓ updated `src/compute_answer.py`, `tests/test_beta.py`
6. ▸ `pytest -q`
6. ✓ `pytest -q`
7. Root cause: compute_answer() returned 0. Updated logic to return 42 for the valid input path. Re-ran pytest to confirm all tests pass.
assistant:
I found the failing assertion in tests/test_beta.py and updated src/compute_answer.py to return the expected value (42). After the change, `pytest -q` reports 12 passed.
turn completed
turn started
9. ▸ `npm test`
9. ✗ `npm test` (exit 127)
10. ✓ warning: Command `npm` not found in PATH (exit 127).
turn failed: Aborted: required dependency `npm` is missing; cannot continue.
stream error: codex exec exited non-zero (1) after turn.failed
thread started
turn started
assistant:
Legacy schema example: hello (item_type=assistant_message).
2. ✓ `echo legacy`
turn completed
thread started
turn started
2. ✓ updated `README.md`
turn completed
+16 -1
View File
@@ -11,7 +11,10 @@ def _loads(lines: str) -> list[dict]:
FIXTURE_PATH = Path(__file__).resolve().parent / "fixtures" / "codex.jsonl"
ALL_FORMATS_FIXTURE_PATH = (
Path(__file__).resolve().parent.parent / "codex_exec_json_all_formats.jsonl"
Path(__file__).resolve().parent / "fixtures" / "codex_exec_json_all_formats.jsonl"
)
ALL_FORMATS_GOLDEN_PATH = (
Path(__file__).resolve().parent / "fixtures" / "codex_exec_json_all_formats.txt"
)
SAMPLE_STREAM = """
@@ -91,6 +94,18 @@ def test_render_event_cli_all_formats_fixture() -> None:
assert any("Legacy schema example" in line for line in out)
def test_render_event_cli_all_formats_golden() -> None:
events = _loads(ALL_FORMATS_FIXTURE_PATH.read_text(encoding="utf-8"))
last_turn = None
out: list[str] = []
for evt in events:
last_turn, lines = render_event_cli(evt, last_turn)
out.extend(lines)
expected = ALL_FORMATS_GOLDEN_PATH.read_text(encoding="utf-8").rstrip("\n")
assert "\n".join(out) == expected
def test_progress_renderer_renders_progress_and_final() -> None:
r = ExecProgressRenderer(max_actions=5)
for evt in _loads(SAMPLE_STREAM):