"""パッケージ骨格の検証(PLAN_02 ステップ 1 / project-structure.md).
仕様上要求されるのは以下.
- `src/tiasjudge/` の src レイアウト.配下に `core/`(診断ロジック)と `gui/`(PySide6 画面)
- `python -m tiasjudge` で起動できるエントリポイント(`__main__.py`)
- 同梱データ `data/` と テスト `tests/`
"""
import importlib
import subprocess
import sys
from pathlib import Path
import pytest
class TestDirectoryLayout:
"""ディレクトリ構成(project-structure.md)."""
@pytest.mark.parametrize(
"relative_path",
[
"src/tiasjudge",
"src/tiasjudge/core",
"src/tiasjudge/gui",
"data",
"tests",
"docs",
],
)
def test_required_directories_exist(self, repo_root: Path, relative_path: str) -> None:
assert (repo_root / relative_path).is_dir()
@pytest.mark.parametrize(
"relative_path",
[
"pyproject.toml",
"src/tiasjudge/__init__.py",
"src/tiasjudge/__main__.py",
"src/tiasjudge/core/__init__.py",
"src/tiasjudge/gui/__init__.py",
"data/data.csv",
"docs/02_ENV/ENV_04_開発コマンド.md",
],
)
def test_required_files_exist(self, repo_root: Path, relative_path: str) -> None:
assert (repo_root / relative_path).is_file()
def test_org_is_not_tracked_by_git(self, repo_root: Path) -> None:
"""旧実装 `org/` は参照専用で Git 管理外(project-structure.md)."""
result = subprocess.run(
["git", "ls-files", "org"],
cwd=repo_root,
capture_output=True,
text=True,
check=True,
)
assert result.stdout.strip() == ""
def test_data_csv_is_tracked_or_stageable(self, repo_root: Path) -> None:
"""同梱データ `data/data.csv` は Git 管理対象(無視されていない)."""
result = subprocess.run(
["git", "check-ignore", "data/data.csv"],
cwd=repo_root,
capture_output=True,
text=True,
)
assert result.returncode != 0, "data/data.csv が .gitignore で除外されている"
class TestImportablePackages:
"""パッケージが import できること."""
@pytest.mark.parametrize(
"module_name",
["tiasjudge", "tiasjudge.core", "tiasjudge.gui", "tiasjudge.__main__"],
)
def test_import(self, module_name: str) -> None:
assert importlib.import_module(module_name) is not None
def test_package_is_installed_from_src_layout(self, repo_root: Path) -> None:
"""import されるパッケージが `src/tiasjudge` であること(editable install)."""
module = importlib.import_module("tiasjudge")
assert module.__file__ is not None
assert Path(module.__file__).resolve().parent == (repo_root / "src" / "tiasjudge").resolve()
def test_version_is_defined(self) -> None:
module = importlib.import_module("tiasjudge")
assert isinstance(module.__version__, str)
assert module.__version__ != ""
class TestEntryPoint:
"""エントリポイント(ENV_04「起動」)."""
def test_main_is_callable_and_returns_exit_code(self) -> None:
main_module = importlib.import_module("tiasjudge.__main__")
assert callable(main_module.main)
assert main_module.main() == 0
def test_python_m_tiasjudge_exits_successfully(self, repo_root: Path) -> None:
"""`python -m tiasjudge` が正常終了する(GUI 未実装でも起動確認は通る)."""
result = subprocess.run(
[sys.executable, "-m", "tiasjudge"],
cwd=repo_root,
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
)
assert result.returncode == 0, result.stderr