"""render.seed(レンダの乱数シード)の仕様ベーステスト.
仕様出典:
- docs/04_SPEC/SPEC_02_シーン定義仕様.md「render」セクション(レンダ設定の YAML スキーマ.
seed は本実装で追加された新フィールドで,仕様書側は Phase 4 の更新対象)
- docs/02_ENV/ENV_04_開発コマンド.md「研究室サーバでの実行」
(同じ YAML・同じ seed でも読み込み直すと画素は変わるが,指標はほぼ一致する.
ノイズの実現を意図的に変えたいときに seed を振る)
検証する仕様:
- seed は省略可能(既定 0)=既存 YAML が書き換え無しで読める(後方互換)
- seed は 0 以上の整数のみ(負値は ValidationError)
- YAML に書いた値がそのまま SceneConfig に載る
"""
from __future__ import annotations
from pathlib import Path
import pytest
import yaml
from pydantic import ValidationError
from sm_tias_lightsim.scene.schema import RenderConfig, SceneConfig, load_scene_yaml
MINIMAL_YAML = Path(__file__).parent.parent / "fixtures" / "minimal.yaml"
# ---------------------------------------------------------------------------
# 既定値・後方互換
# ---------------------------------------------------------------------------
def test_seed_defaults_to_zero():
"""seed を省略すると 0 になること(既定値)."""
assert RenderConfig().seed == 0
def test_existing_yaml_without_seed_is_still_valid():
"""seed を書いていない既存 YAML がそのまま読め,seed=0 になること(後方互換)."""
config = load_scene_yaml(MINIMAL_YAML)
assert config.render.seed == 0
def test_seed_omission_does_not_change_other_render_fields():
"""seed の追加で他の render 設定の既定値が変わっていないこと."""
render = RenderConfig()
assert render.variant == "llvm_ad_rgb"
assert render.integrator == "path"
assert render.max_depth == 8
assert render.spp == 256
# ---------------------------------------------------------------------------
# 正常系: 値の指定
# ---------------------------------------------------------------------------
@pytest.mark.parametrize("seed", [0, 1, 2, 42, 12345])
def test_seed_accepts_non_negative_integers(seed):
"""0 以上の整数はそのまま保持されること."""
assert RenderConfig(seed=seed).seed == seed
def test_seed_from_yaml_is_loaded(tmp_path: Path):
"""YAML の render.seed が SceneConfig に反映されること."""
data = yaml.safe_load(MINIMAL_YAML.read_text(encoding="utf-8"))
data["render"]["seed"] = 7
# メッシュの相対パスを保つため,YAML はフィクスチャと同じディレクトリ基準で解決する
yaml_path = tmp_path / "scene_with_seed.yaml"
yaml_path.write_text(yaml.safe_dump(data, allow_unicode=True), encoding="utf-8")
config = SceneConfig.model_validate(yaml.safe_load(yaml_path.read_text(encoding="utf-8")))
assert config.render.seed == 7
# ---------------------------------------------------------------------------
# 異常系
# ---------------------------------------------------------------------------
@pytest.mark.parametrize("seed", [-1, -42])
def test_negative_seed_raises_validation_error(seed):
"""負の seed は ValidationError になること(ge=0)."""
with pytest.raises(ValidationError):
RenderConfig(seed=seed)
def test_non_integer_seed_raises_validation_error():
"""整数に解釈できない seed は ValidationError になること."""
with pytest.raises(ValidationError):
RenderConfig(seed="abc")
def test_float_seed_with_fraction_raises_validation_error():
"""小数の seed は ValidationError になること(整数フィールド)."""
with pytest.raises(ValidationError):
RenderConfig(seed=1.5)