Download tests/test_cli.py from hkblockchaintechnology/tiny-computer-agent: direct link, hf CLI and curl.
- Browser
- Download file 8.54 kB
-
https://huggingface.co/hkblockchaintechnology/tiny-computer-agent/resolve/main/tests/test_cli.py
- Command line
-
hf download hf://hkblockchaintechnology/tiny-computer-agent/tests/test_cli.py
-
curl -L -o test_cli.py https://huggingface.co/hkblockchaintechnology/tiny-computer-agent/resolve/main/tests/test_cli.py
8.54 kB
| import json | |
| import pytest | |
| from tiny_computer_agent import __main__ as cli | |
| from tiny_computer_agent import verify_audit | |
| def test_demo_runs_dry_run_by_default(capsys): | |
| assert cli.main([]) == 0 | |
| out = capsys.readouterr().out | |
| assert "dry-run" in out | |
| assert "(dry-run) would click" in out | |
| assert "result: success" in out | |
| def test_real_input_needs_the_allow_env_var(monkeypatch, capsys): | |
| monkeypatch.delenv(cli.ALLOW_REAL_INPUT_ENV, raising=False) | |
| assert cli.main(["--real-input"]) == 2 | |
| assert "refusing --real-input" in capsys.readouterr().err | |
| def test_bad_script_json_is_reported(capsys): | |
| assert cli.main(["--script", "{not json"]) == 2 | |
| assert "not valid JSON" in capsys.readouterr().err | |
| def test_script_replay(capsys): | |
| assert cli.main(["--script", '[{"kind": "done", "reason": "nothing to do"}]']) == 0 | |
| assert "nothing to do" in capsys.readouterr().out | |
| def test_failure_exit_code(capsys): | |
| # the planner gives up when the target never appears, so the CLI exits non-zero | |
| assert cli.main(["click 'Nonexistent button'"]) == 1 | |
| assert "gave up" in capsys.readouterr().out | |
| def test_doctor_exits_with_a_status(capsys): | |
| assert cli.main(["--doctor"]) in (0, 1) | |
| assert "preflight" in capsys.readouterr().out | |
| def test_live_is_refused_without_a_display(capsys, monkeypatch): | |
| from tiny_computer_agent.desktop import display_available | |
| if display_available()[0]: | |
| pytest.skip("this machine has a display, so --live would really run") | |
| assert cli.main(["--live"]) == 2 | |
| captured = capsys.readouterr() | |
| assert "refusing to run live" in captured.err | |
| assert "no DISPLAY" in captured.out | |
| def test_screenshot_replay_needs_no_display(capsys): | |
| """The whole pipeline - OCR index, menu, action - on a still image.""" | |
| from conftest import require_ocr | |
| require_ocr() # one tested guard, shared with the perception tests | |
| assert cli.main(["--image", "example", "--brain", "planner"]) == 0 | |
| out = capsys.readouterr().out | |
| assert "screenshot replay" in out | |
| assert "elements detected" in out | |
| assert "would click" in out | |
| def test_a_missing_image_is_reported_not_crashed(capsys): | |
| assert cli.main(["--image", "/nonexistent/shot.png"]) == 2 | |
| assert "could not start" in capsys.readouterr().err | |
| def test_vlm_brain_requires_a_live_screen(capsys): | |
| assert cli.main(["--brain", "vlm"]) == 2 | |
| assert "needs --live" in capsys.readouterr().err | |
| # --- 2.0: the subcommands, which are how a run becomes a habit --------------- # | |
| def test_skills_list_on_an_empty_library_says_how_to_start(tmp_path, capsys): | |
| assert cli.main(["skills", "list", "--path", str(tmp_path / "none.json")]) == 0 | |
| assert "no skills" in capsys.readouterr().out | |
| def test_learning_refuses_without_evidence(tmp_path, capsys): | |
| code = cli.main(["skills", "learn", "click 'Save'", | |
| "--script", '[{"kind": "click", "label": "Save"}]', | |
| "--path", str(tmp_path / "skills.json")]) | |
| assert code == 2 | |
| assert "refusing to learn" in capsys.readouterr().err | |
| def test_learn_then_list_then_show_then_remove(tmp_path, capsys): | |
| path = str(tmp_path / "skills.json") | |
| script = '[{"kind": "click", "label": "Files"}, {"kind": "click", "label": "Save"}]' | |
| assert cli.main(["skills", "learn", "click 'Save' to save the document", | |
| "--script", script, "--verify-gone", "Name", "--path", path]) == 0 | |
| assert "learned 'save-document'" in capsys.readouterr().out | |
| assert cli.main(["skills", "list", "--path", path]) == 0 | |
| out = capsys.readouterr().out | |
| assert "save-document" in out and "verified" in out | |
| assert cli.main(["skills", "show", "save-document", "--path", path]) == 0 | |
| assert "'Name' goes away" in capsys.readouterr().out | |
| assert cli.main(["skills", "remove", "save-document", "--path", path]) == 0 | |
| assert "removed" in capsys.readouterr().out | |
| assert cli.main(["skills", "show", "save-document", "--path", path]) == 1 | |
| def test_a_learned_skill_can_be_replayed_by_the_brain(tmp_path): | |
| """The point of the whole feature: the second run needs no script.""" | |
| path = tmp_path / "skills.json" | |
| script = '[{"kind": "click", "label": "Files"}, {"kind": "click", "label": "Save"}]' | |
| assert cli.main(["skills", "learn", "click 'Save' to save the document", | |
| "--script", script, "--verify-gone", "Name", "--path", str(path)]) == 0 | |
| from tiny_computer_agent import SkillBrain, SkillLibrary | |
| from tiny_computer_agent.__main__ import demo_screen | |
| from tiny_computer_agent.loop import AgentLoop | |
| library = SkillLibrary.load(path) | |
| loop = AgentLoop(screen=demo_screen(), brain=SkillBrain(library)) | |
| episode = loop.run("click 'Save' to save the document") | |
| assert [s.action.label for s in episode.steps if s.action and s.action.kind == "click"] \ | |
| == ["Files", "Save"] | |
| def test_batch_runs_a_queue_and_exits_on_its_report(tmp_path, capsys): | |
| tasks = tmp_path / "tasks.json" | |
| tasks.write_text(json.dumps([{"goal": "click 'Save' to save the document", | |
| "verify_gone": "Name"}, | |
| {"goal": "click 'Files' to open the file manager", | |
| "verify_text": "untitled"}])) | |
| state = tmp_path / "state.jsonl" | |
| report = tmp_path / "report.json" | |
| assert cli.main(["batch", str(tasks), "--state", str(state), "--report", str(report)]) == 0 | |
| out = capsys.readouterr().out | |
| assert "2/2 verified" in out | |
| assert json.loads(report.read_text())["passed"] == 2 | |
| assert cli.main(["batch", str(tasks), "--state", str(state)]) == 0 | |
| assert "already run" in capsys.readouterr().out | |
| def test_batch_rejects_tasks_that_are_not_tasks(tmp_path, capsys): | |
| bad = tmp_path / "bad.json" | |
| bad.write_text(json.dumps([{"nothing": "here"}])) | |
| assert cli.main(["batch", str(bad)]) == 2 | |
| assert "needs at least a 'goal'" in capsys.readouterr().err | |
| missing = tmp_path / "absent.json" | |
| assert cli.main(["batch", str(missing)]) == 2 | |
| assert "cannot read" in capsys.readouterr().err | |
| # -- 2.0: the operator's gate, and a record of the run that can be checked ------- # | |
| SCRIPT = '[{"kind": "click", "label": "Save"}, {"kind": "done", "reason": "saved"}]' | |
| def test_the_audit_flag_writes_a_chain_that_verifies(tmp_path, capsys): | |
| path = tmp_path / "run.jsonl" | |
| assert cli.main(["--image", "example", "--script", SCRIPT, "--audit", str(path)]) == 0 | |
| out = capsys.readouterr().out | |
| assert "recording this run to" in out | |
| assert "audit:" in out and "chain intact" in out | |
| ok, detail = verify_audit(path) | |
| assert ok, detail | |
| def test_verify_audit_accepts_an_intact_chain(tmp_path, capsys): | |
| path = tmp_path / "run.jsonl" | |
| cli.main(["--image", "example", "--script", SCRIPT, "--audit", str(path)]) | |
| assert cli.main(["--verify-audit", str(path)]) == 0 | |
| assert "ok" in capsys.readouterr().out | |
| def test_verify_audit_fails_loudly_on_a_tampered_chain(tmp_path, capsys): | |
| path = tmp_path / "run.jsonl" | |
| cli.main(["--image", "example", "--script", SCRIPT, "--audit", str(path)]) | |
| lines = path.read_text(encoding="utf-8").splitlines() | |
| entry = json.loads(lines[0]) | |
| entry["outcome"] = "nothing happened" # a nicer story | |
| lines[0] = json.dumps(entry, sort_keys=True, separators=(",", ":")) | |
| path.write_text("\n".join(lines) + "\n", encoding="utf-8") | |
| assert cli.main(["--verify-audit", str(path)]) == 1 | |
| out = capsys.readouterr().out | |
| assert "FAIL" in out and "entry 1" in out | |
| def test_a_bad_gate_spec_is_a_usage_error(capsys): | |
| assert cli.main(["--gate", "yes-please"]) == 2 | |
| assert "bad --gate" in capsys.readouterr().err | |
| def test_the_read_only_gate_refuses_to_change_anything(capsys): | |
| """The gate is the operator's yes; read-only means the answer is no to any change.""" | |
| code = cli.main(["--image", "example", "--script", | |
| '[{"kind": "click", "label": "Save"}]', "--gate", "read-only"]) | |
| out = capsys.readouterr().out | |
| assert code == 1, "a refused action is a failed episode, not a success" | |
| assert "gate: read-only" in out | |
| assert "operator refused" in out and "read-only gate" in out | |
| def test_the_labels_gate_lets_a_whitelisted_click_through(capsys): | |
| code = cli.main(["--image", "example", "--script", SCRIPT, "--gate", "labels:Save"]) | |
| out = capsys.readouterr().out | |
| assert code == 0, out | |
| assert "is whitelisted" in out or "would click" in out | |