67 lines
2.3 KiB
Python
67 lines
2.3 KiB
Python
|
|
"""Unit-Tests Fixture-Generator (PLAN.md §16.3, §16.4)."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import csv
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from fixture_generator import LAYER64, MASTER32, write_csv
|
||
|
|
|
||
|
|
|
||
|
|
def test_master32_has_exactly_32_contiguous_channels() -> None:
|
||
|
|
assert len(MASTER32) == 32
|
||
|
|
assert [row[0] for row in MASTER32] == list(range(1, 33))
|
||
|
|
|
||
|
|
|
||
|
|
def test_layer64_has_exactly_64_contiguous_channels() -> None:
|
||
|
|
assert len(LAYER64) == 64
|
||
|
|
assert [row[0] for row in LAYER64] == list(range(1, 65))
|
||
|
|
|
||
|
|
|
||
|
|
def test_master32_key_channels_match_plan() -> None:
|
||
|
|
by_channel = {row[0]: row for row in MASTER32}
|
||
|
|
assert "Blackout" in by_channel[3][1] # Kanal 3 Blackout
|
||
|
|
assert "Preset Recall" in by_channel[8][1] # Kanal 8 steigende Flanke
|
||
|
|
assert "Tap Tempo" in by_channel[16][1] # Kanal 16 Tap
|
||
|
|
|
||
|
|
|
||
|
|
def test_layer64_key_channels_match_plan() -> None:
|
||
|
|
by_channel = {row[0]: row for row in LAYER64}
|
||
|
|
assert "Layer Enable" in by_channel[1][1]
|
||
|
|
assert "Opacity" in by_channel[2][1]
|
||
|
|
assert "Load/Commit" in by_channel[9][1]
|
||
|
|
assert "Blend Mode" in by_channel[21][1]
|
||
|
|
assert "FX1 Enable" in by_channel[41][1]
|
||
|
|
assert "FX2 Enable" in by_channel[52][1]
|
||
|
|
assert "Retrigger" in by_channel[63][1]
|
||
|
|
|
||
|
|
|
||
|
|
def test_layer64_fx_parameter_blocks() -> None:
|
||
|
|
by_channel = {row[0]: row for row in LAYER64}
|
||
|
|
for slot in range(1, 9):
|
||
|
|
assert f"P{slot}" in by_channel[43 + slot][1]
|
||
|
|
assert f"P{slot}" in by_channel[54 + slot][1]
|
||
|
|
|
||
|
|
|
||
|
|
def test_eight_layers_fit_exactly_one_universe() -> None:
|
||
|
|
# §16.2: „Acht Layer entsprechen damit exakt einem DMX-Universe“
|
||
|
|
assert 8 * len(LAYER64) == 512
|
||
|
|
|
||
|
|
|
||
|
|
def test_write_csv_output(tmp_path: Path) -> None:
|
||
|
|
out = tmp_path / "layer64" / "layer64.csv"
|
||
|
|
write_csv(LAYER64, out)
|
||
|
|
with open(out, encoding="utf-8", newline="") as fh:
|
||
|
|
rows = list(csv.reader(fh))
|
||
|
|
assert rows[0] == ["channel", "parameter", "resolution_behavior"]
|
||
|
|
assert len(rows) == 65 # Header + 64
|
||
|
|
assert rows[1] == ["1", "Layer Enable", "Schalter"]
|
||
|
|
|
||
|
|
|
||
|
|
def test_write_csv_rejects_gaps(tmp_path: Path) -> None:
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
broken = [(1, "a", "x"), (3, "b", "y")] # Kanal 2 fehlt
|
||
|
|
with pytest.raises(ValueError, match="contiguous"):
|
||
|
|
write_csv(broken, tmp_path / "broken.csv") # ValueError vor dem Schreiben
|