テストコード(tests/**・test_*.py・conftest.py)を追加・編集するときは本ルールに従うこと.
- フレームワーク: pytest
- 配置:
tests/ 配下に src/tias_judge_model/ の構造をミラーする
- カバレッジ目標: 数値目標なし.代わりに「下記の必須対象は必ず単体テストを書く」を徹底する
- 臨床データを使うテストは書かない.テストは合成データ(小さいランダム画像と合成 manifest)のみで完結させる.手元でもサーバでも同じテストが通ること
- 実行コマンドは ENV_04 開発コマンドを参照する
- ファイル:
test_<対象モジュール>.py
- 関数:
test_<振る舞い>(例: test_split_keeps_patients_disjoint)
- クラス(任意):
Test<クラス名> で振る舞いごとにグループ化してよい
- 患者単位分割: 同一
patient_id が train / val / test に跨らないこと.最重要(破れると評価が無意味になる).同じ seed で分割が再現することも確認する
- manifest のバリデーション:
patient_id 欠落・未知ラベル・重複行で停止すること(黙って除外しないこと)
- 指標計算: 既知の混同行列に対して macro F1・クラス別 precision / recall が期待値と一致すること.クラス ID の順序が固定されていること
- 回収ホワイトリスト: 画像・
manifest.csv・個票の予測結果が回収対象に入らないこと(SPEC_01の制約をテストで固定する)
- 設定スキーマ: 不正な YAML が
ValidationError になること.必須フィールドの欠落を検出すること
- CLI のエントリポイント: 統合テスト 1 本でカバーする
- 図の生成: 見栄えはテストしにくいため「ファイルが生成されたか」の smoke テストで十分
- ssh・リモート実行はモックする.テストが実サーバに接続してはならない(転送コマンドの組み立て・回収対象の判定など,純粋なロジックを検証する)
- ファイル I/O はモックしない.
tmp_path フィクスチャで実ファイルを使う
- モデルの学習はモックしないが,合成データ・極小モデル・1 エポックで回す(下記 slow マーカー)
- 乱数を含むテストは必ず seed を固定する
学習を回すテストは @pytest.mark.slow を付けて区別する.
import pytest
@pytest.mark.slow
def test_train_one_epoch_on_synthetic_data():
...
- 通常実行(高速):
uv run pytest -m "not slow"
- 全テスト実行:
uv run pytest
マーカーは pyproject.toml の [tool.pytest.ini_options] に登録する.
- Phase 1(実装 / coder): 機能実装 → 人間が動作確認
- Phase 2(テスト / tester): 本方針に従いテストを追加
- Phase 3(リファクタ / refactorer): テストを safety net として品質改善
- Phase 4: ドキュメント更新
Phase 2 でテストが書きにくいと感じたら設計が悪いシグナルである.Phase 3 でモジュールを分割するか責務を見直す.
- 仕様変更による失敗: 先に SPEC を更新してからテストを書き直す
- バグ起因の失敗: 修正してから再実行する
- flaky なテスト: seed 固定漏れか,学習の非決定性に依存した期待値を疑う(学習結果の数値を直接期待値にしない)