# テスト方針 (Test Policy)

## 基本方針 (Basic Policy)

- フレームワーク: **pytest**
- 配置: `tests/` 配下に `src/sm_tias_lightsim/` のサブパッケージ構造をミラー
- カバレッジ目標: **数値目標なし**．代わりに「核となる計算ロジックは必ず単体テスト」というルールを徹底する
- 通常実行: `uv run pytest`
- 重いテストを含む実行: `uv run pytest -m "" --no-strict-markers` ／ デフォルトでスキップは `-m "not slow"`

## テストの配置

```
tests/
├── conftest.py             # 共通フィクスチャ
├── fixtures/               # テストデータ（小さい STL / 既知の輝度マップ等）
├── geometry/
│   └── test_loader.py
├── scene/
│   ├── test_builder.py
│   └── test_schema.py
├── render/
│   └── test_runner.py      # 軽量シーンの end-to-end
├── test_uniformity.py      # MiniTias-Evaluation 互換の数値検証
└── evaluation/
    ├── test_roi.py
    └── test_zones.py
```

## ファイル・関数命名

- ファイル: `test_<対象モジュール>.py`
- 関数: `test_<振る舞い>` 例: `test_grayscale_conversion_uses_rec709_coefficients`
- クラス（任意）: `Test<クラス名>` で振る舞いごとにグループ化可能

## 必ずテストを書く対象 (Mandatory)

- **核計算ロジック**: `uniformity.py`, `evaluation/zones.py`, `evaluation/radial.py`
  - 既知の入力（合成輝度マップ）に対して期待値を確認
  - MiniTias-Evaluation の元実装と数値が一致することを保証
- **入力バリデーション**: `scene/schema.py`
  - 不正 YAML が `ValidationError` を投げること
  - 必須フィールド欠落・参照不整合を検出すること
- **データ変換**: `geometry/transforms.py`（mm ↔ m 等）
  - 変換が可逆であること
- **YAML → Mitsuba scene 変換**: `scene/builder.py`
  - 期待される scene dict を生成すること（実レンダリングはせず構造のみ確認）

## テストを必須としない対象 (Optional)

- **CLI のエントリポイント**（`cli/render.py`, `cli/evaluate.py`）
  - 統合テスト 1 本でカバー
- **可視化**（`evaluation/visualize.py`）
  - 図の見栄えはテストしにくい．「ファイルが生成されたか」程度の smoke テストで十分

## モック方針 (Mocking)

- **Mitsuba をモックしない**．小さい合成シーン（64×64 等）で実物を回す
  - 理由: モックすると物理量の妥当性検証ができなくなる．実機との比較が目的のため
- **ファイル I/O はモックしない**．`tmp_path` フィクスチャで実ファイルを使う
- **乱数を含むテスト**は必ず `seed` を固定する

## 重いテストの扱い (Slow Tests)

レンダリングを伴うテストは `@pytest.mark.slow` を付けて区別：

```python
import pytest


@pytest.mark.slow
def test_render_baseline_matches_reference():
    ...
```

- 通常実行（高速）: `uv run pytest -m "not slow"`
- 全テスト実行（CI 等）: `uv run pytest`

マーカー定義は `pyproject.toml` の `[tool.pytest.ini_options]` に登録済み．

## /implement パイプラインでのテスト

`/implement` の流れ：

1. **Phase 1（実装 / coder）**: 機能実装 → 人間が動作確認
2. **Phase 2（テスト / tester）**: この方針に従いテストを追加
3. **Phase 3（リファクタ / refactorer）**: テストを safety net として品質改善
4. **Phase 4**: ドキュメント更新

Phase 2 でテストが書きにくいと感じたら，それは設計が悪いシグナル．Phase 3 でモジュールを分割するか責務を見直す．

## テスト失敗時の運用

- ルール変更による失敗: 規約・仕様を改める根拠があれば SPEC / GUIDE を先に更新してからテストを書き直す
- バグ起因の失敗: 修正してから再実行
- 単に flaky なテスト: `seed` 固定漏れか，乱数依存の境界値．`seed` を見直す

## 参考 (References)

- [pytest documentation](https://docs.pytest.org/)
- [Mitsuba 3 — Differentiable rendering tutorials](https://mitsuba.readthedocs.io/en/stable/) （小規模シーンの組み立て例）
