mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 22:27:01 +01:00
Partitioned at the section banners each file already used, into ten new modules named for what they cover. python_pkg/code_tutor is now entirely under the cap, from thirteen violations. The splitter copies the whole original header into each new file and lets ruff's F401 pass prune it - 59 imports removed correctly, versus a hand-written import block failing on every earlier test split today. That does not cover module-level helpers: _make_verifier sat between two banners and was left behind by its callers, so it moved to conftest.py, taking test_verifier.py's shadowing copy of _make_live_mock with it. No patch string changed. Pass count is 217 before and after. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
127 lines
4.2 KiB
Python
127 lines
4.2 KiB
Python
"""Tests for the code_tutor CLI commands themselves."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import requests
|
|
from typer.testing import CliRunner
|
|
|
|
from python_pkg.code_tutor.cli import app
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
def _make_plan(codebase: Path, fingerprint: str = "abc") -> dict:
|
|
return {
|
|
"codebase_path": str(codebase),
|
|
"created_at": "2026-01-01T00:00:00+00:00",
|
|
"total_items": 2,
|
|
"source_fingerprint": fingerprint,
|
|
"sessions": [
|
|
{
|
|
"id": 1,
|
|
"title": "mod",
|
|
"items": [
|
|
{
|
|
"id": "mod.fn",
|
|
"file": "mod.py",
|
|
"type": "function",
|
|
"name": "fn",
|
|
"start_line": 1,
|
|
"end_line": 3,
|
|
"class_name": "",
|
|
"depends_on": [],
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# analyze command
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_analyze_not_dir(tmp_path: Path) -> None:
|
|
result = runner.invoke(app, ["analyze", str(tmp_path / "no_such_dir")])
|
|
assert result.exit_code == 1
|
|
|
|
|
|
def test_analyze_no_items(tmp_path: Path) -> None:
|
|
with patch("python_pkg.code_tutor.cli.extract_items", return_value=[]):
|
|
result = runner.invoke(app, ["analyze", str(tmp_path)])
|
|
assert result.exit_code == 0
|
|
|
|
|
|
def test_analyze_with_items(tmp_path: Path) -> None:
|
|
mock_items = [MagicMock()]
|
|
mock_plan = _make_plan(tmp_path)
|
|
with (
|
|
patch("python_pkg.code_tutor.cli.extract_items", return_value=mock_items),
|
|
patch("python_pkg.code_tutor.cli.build_plan", return_value=mock_plan),
|
|
patch("python_pkg.code_tutor.cli.save_plan"),
|
|
patch("python_pkg.code_tutor.cli.config_dir", return_value=tmp_path),
|
|
):
|
|
result = runner.invoke(app, ["analyze", str(tmp_path)])
|
|
assert result.exit_code == 0
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# study command
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_study_not_dir(tmp_path: Path) -> None:
|
|
result = runner.invoke(app, ["study", str(tmp_path / "no_such_dir")])
|
|
assert result.exit_code == 1
|
|
|
|
|
|
def test_study_no_plan(tmp_path: Path) -> None:
|
|
with patch("python_pkg.code_tutor.cli.load_plan", return_value=None):
|
|
result = runner.invoke(app, ["study", str(tmp_path)])
|
|
assert result.exit_code == 1
|
|
|
|
|
|
def test_study_ollama_fails(tmp_path: Path) -> None:
|
|
plan = _make_plan(tmp_path)
|
|
with (
|
|
patch("python_pkg.code_tutor.cli.load_plan", return_value=plan),
|
|
patch("python_pkg.code_tutor.cli._ensure_fresh_plan", return_value=plan),
|
|
patch("python_pkg.code_tutor.cli._ensure_ollama_running", return_value=False),
|
|
):
|
|
result = runner.invoke(app, ["study", str(tmp_path)])
|
|
assert result.exit_code == 1
|
|
|
|
|
|
def test_study_connection_error(tmp_path: Path) -> None:
|
|
plan = _make_plan(tmp_path)
|
|
with (
|
|
patch("python_pkg.code_tutor.cli.load_plan", return_value=plan),
|
|
patch("python_pkg.code_tutor.cli._ensure_fresh_plan", return_value=plan),
|
|
patch("python_pkg.code_tutor.cli._ensure_ollama_running", return_value=True),
|
|
patch(
|
|
"python_pkg.code_tutor.cli.run_session",
|
|
side_effect=requests.exceptions.ConnectionError(),
|
|
),
|
|
):
|
|
result = runner.invoke(app, ["study", str(tmp_path)])
|
|
assert result.exit_code == 1
|
|
|
|
|
|
def test_study_success(tmp_path: Path) -> None:
|
|
plan = _make_plan(tmp_path)
|
|
with (
|
|
patch("python_pkg.code_tutor.cli.load_plan", return_value=plan),
|
|
patch("python_pkg.code_tutor.cli._ensure_fresh_plan", return_value=plan),
|
|
patch("python_pkg.code_tutor.cli._ensure_ollama_running", return_value=True),
|
|
patch("python_pkg.code_tutor.cli.run_session"),
|
|
):
|
|
result = runner.invoke(app, ["study", str(tmp_path)])
|
|
assert result.exit_code == 0
|