Files
gaokao-volunteer-system/tests/test_majors_cli_phase2.py

161 lines
5.3 KiB
Python
Raw Normal View History

from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[1]
SCRIPT_PATH = PROJECT_ROOT / "scripts" / "gaokao-cli"
def _write_catalog(root: Path) -> None:
national = root / "national"
national.mkdir(parents=True, exist_ok=True)
changes = root / "changes"
changes.mkdir(parents=True, exist_ok=True)
payload = {
"year": 2024,
"version": "2024.1",
"coverage_mode": "mvp_subset",
"source": "教育部普通高等学校本科专业目录(人工摘录校对)",
"source_url": "https://www.moe.gov.cn/",
"last_verified_at": "2026-06-17",
"majors": [
{
"code": "020101",
"name": "经济学",
"discipline": "经济学",
"category": "经济学类",
"degree": "经济学学士",
"is_directional": False,
"status": "active",
"year_added": 1998,
"year_removed": None,
"notes": None,
},
{
"code": "080901",
"name": "计算机科学与技术",
"discipline": "工学",
"category": "计算机类",
"degree": "工学学士",
"is_directional": False,
"status": "active",
"year_added": 1998,
"year_removed": None,
"notes": None,
},
{
"code": "120201K",
"name": "工商管理",
"discipline": "管理学",
"category": "工商管理类",
"degree": "管理学学士",
"is_directional": True,
"status": "renamed",
"year_added": 1998,
"year_removed": 2024,
"notes": "示例改名专业",
},
],
}
(national / "2024.json").write_text(
json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8"
)
(national / "latest.json").write_text(
json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8"
)
(changes / "2024-2026.md").write_text(
"# changes\n\n- sample\n", encoding="utf-8"
)
def _run_cli(*args: str) -> subprocess.CompletedProcess[str]:
return subprocess.run(
[sys.executable, str(SCRIPT_PATH), *args],
cwd=PROJECT_ROOT,
capture_output=True,
text=True,
)
def test_majors_status_cli_reports_catalog_summary(tmp_path: Path) -> None:
_write_catalog(tmp_path)
result = _run_cli("majors", "status", "--catalog-root", str(tmp_path), "--json")
assert result.returncode == 0, result.stderr
payload = json.loads(result.stdout)
assert payload["ok"] is True
assert payload["year"] == 2024
assert payload["version"] == "2024.1"
assert payload["major_count"] == 3
assert payload["change_count"] == 1
assert payload["risky_major_count"] == 1
assert payload["coverage_mode"] == "mvp_subset"
assert "changes/2024-2026.md" in payload["version_strategy"]
def test_majors_lookup_cli_supports_name_and_code(tmp_path: Path) -> None:
_write_catalog(tmp_path)
result = _run_cli(
"majors", "lookup", "经济学", "--catalog-root", str(tmp_path), "--json"
)
assert result.returncode == 0, result.stderr
payload = json.loads(result.stdout)
assert payload["ok"] is True
assert payload["major"]["code"] == "020101"
result = _run_cli(
"majors", "lookup", "080901", "--catalog-root", str(tmp_path), "--json"
)
assert result.returncode == 0, result.stderr
payload = json.loads(result.stdout)
assert payload["ok"] is True
assert payload["major"]["name"] == "计算机科学与技术"
def test_majors_verify_cli_checks_required_national_files(tmp_path: Path) -> None:
_write_catalog(tmp_path)
result = _run_cli("majors", "verify", "--catalog-root", str(tmp_path), "--json")
assert result.returncode == 0, result.stderr
payload = json.loads(result.stdout)
assert payload["ok"] is True
assert payload["missing_required_files"] == []
assert payload["major_count"] == 3
assert payload["change_count"] == 1
assert payload["risky_major_count"] == 1
assert "changes/2024-2026.md" in payload["version_strategy"]
def test_majors_lookup_cli_returns_business_error_when_missing(tmp_path: Path) -> None:
_write_catalog(tmp_path)
result = _run_cli(
"majors", "lookup", "不存在的专业", "--catalog-root", str(tmp_path), "--json"
)
assert result.returncode == 1
payload = json.loads(result.stdout)
assert payload["ok"] is False
assert payload["code"] == "E_MAJORS_NOT_FOUND"
def test_majors_changes_cli_lists_non_active_majors(tmp_path: Path) -> None:
_write_catalog(tmp_path)
result = _run_cli("majors", "changes", "--catalog-root", str(tmp_path), "--json")
assert result.returncode == 0, result.stderr
payload = json.loads(result.stdout)
assert payload["ok"] is True
assert payload["change_count"] == 1
assert payload["changes"][0]["code"] == "120201K"
assert payload["changes"][0]["status"] == "renamed"
assert "non_active" in payload["changes"][0]["risk_tags"]