"""Tests for the `timmy learn` CLI command (autoresearch entry point).""" from unittest.mock import MagicMock, patch from typer.testing import CliRunner from timmy.cli import app runner = CliRunner() class TestLearnCommand: """Tests for `timmy learn`.""" def test_requires_target(self): result = runner.invoke(app, ["learn"]) assert result.exit_code != 0 assert "target" in result.output.lower() or "target" in (result.stderr or "").lower() def test_dry_run_shows_hypothesis_no_tox(self, tmp_path): program_file = tmp_path / "program.md" program_file.write_text("Improve logging coverage in agent module") with patch("timmy.autoresearch.subprocess.run") as mock_run: result = runner.invoke( app, [ "learn", "--target", "src/timmy/agent.py", "--program", str(program_file), "--max-experiments", "2", "--dry-run", ], ) assert result.exit_code == 0 # tox should never be called in dry-run mock_run.assert_not_called() assert "agent.py" in result.output def test_missing_program_md_warns_but_continues(self, tmp_path): with patch("timmy.autoresearch.subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0, stdout="3 passed", stderr="") result = runner.invoke( app, [ "learn", "--target", "src/timmy/agent.py", "--program", str(tmp_path / "nonexistent.md"), "--max-experiments", "1", "--dry-run", ], ) assert result.exit_code == 0 def test_dry_run_prints_max_experiments_hypotheses(self, tmp_path): program_file = tmp_path / "program.md" program_file.write_text("Fix edge case in parser") result = runner.invoke( app, [ "learn", "--target", "src/timmy/parser.py", "--program", str(program_file), "--max-experiments", "3", "--dry-run", ], ) assert result.exit_code == 0 # Should show 3 experiment headers assert result.output.count("[1/3]") == 1 assert result.output.count("[2/3]") == 1 assert result.output.count("[3/3]") == 1 def test_help_text_present(self): result = runner.invoke(app, ["learn", "--help"]) assert result.exit_code == 0 assert "--target" in result.output assert "--metric" in result.output assert "--budget" in result.output assert "--max-experiments" in result.output assert "--dry-run" in result.output