Expand test suite from 17 to 29 tests covering all new features
New test cases: - UNIT_18-20: vertical tracklist parser (basic, no-duration, no false-positives) - UNIT_21: single-CD tracklist match without disc_number - UNIT_22-24: genre normalization (German, English variants, titlecase) - UNIT_25-28: _is_classical() — correct triggers and false-positive prevention - UNIT_29: cover normalization (Front.jpg → folder.jpg rename) All 29/29 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ec8a37f313
commit
071f4c5e1d
1 changed files with 147 additions and 0 deletions
|
|
@ -188,6 +188,140 @@ def test_extract_hints_multi_disc() -> str:
|
|||
return f"disc numbers detected: {disc_nums}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Vertical tracklist parser Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_vertical_tracklist_basic() -> str:
|
||||
from hint_extractor import _normalize_vertical_tracklist
|
||||
text = "1\nKatka dovádí\n3:22\n2\nZáludná\n2:15\n3\nPolka pro trubku\n4:01"
|
||||
result = _normalize_vertical_tracklist(text)
|
||||
assert result is not None, "should recognize vertical format"
|
||||
assert "1. Katka" in result, f"got: {result!r}"
|
||||
assert "2. Záludná" in result, f"got: {result!r}"
|
||||
return f"normalized: {result[:60]!r}"
|
||||
|
||||
|
||||
def test_vertical_tracklist_without_duration() -> str:
|
||||
from hint_extractor import _normalize_vertical_tracklist
|
||||
text = "1\nFirst Song\n2\nSecond Song\n3\nThird Song"
|
||||
result = _normalize_vertical_tracklist(text)
|
||||
assert result is not None, "should work without durations"
|
||||
assert "1. First Song" in result, f"got: {result!r}"
|
||||
return f"no-duration OK: {result[:60]!r}"
|
||||
|
||||
|
||||
def test_vertical_tracklist_not_triggered_for_normal() -> str:
|
||||
from hint_extractor import _normalize_vertical_tracklist
|
||||
text = "1. Dancing Queen\n2. Waterloo\n3. Fernando"
|
||||
result = _normalize_vertical_tracklist(text)
|
||||
assert result is None, f"should return None for normal format, got: {result!r}"
|
||||
return "correctly returns None for standard format"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Single-CD disc handling Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_single_cd_tracklist_match() -> str:
|
||||
"""Track-Nummer-Match darf nicht disc_num erfordern (Single-CD hat disc=None)."""
|
||||
from hint_extractor import _parse_tracklist
|
||||
from models import TrackHints, AlbumHints, AlbumScan
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
root = Path(tmpdir) / "Tufaranka_-_Katka_dovadi"
|
||||
root.mkdir()
|
||||
(root / "01_-_Tufaranka_-_AudioTrack_01.mp3").write_bytes(b"\x00" * 100)
|
||||
(root / "tracklist.txt").write_text("1\nKatka dovádí\n3:22\n2\nZáludná\n2:15\n3\nPolka\n4:01")
|
||||
|
||||
from scanner import scan_album
|
||||
from hint_extractor import extract_hints
|
||||
scan = scan_album(root)
|
||||
hints = extract_hints(scan, use_ocr=False)
|
||||
track = hints.tracks[0]
|
||||
assert track.title == "Katka dovádí", f"expected tracklist title, got: {track.title!r}"
|
||||
return f"single-CD match OK: title={track.title!r}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Genre normalization Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_genre_normalize_german() -> str:
|
||||
from metadata_resolver import normalize_genre
|
||||
assert normalize_genre("volksmusik") == "Folk", "volksmusik → Folk"
|
||||
assert normalize_genre("klassik") == "Classical", "klassik → Classical"
|
||||
assert normalize_genre("marschmusik") == "March", "marschmusik → March"
|
||||
return "German genres normalized correctly"
|
||||
|
||||
|
||||
def test_genre_normalize_english_variants() -> str:
|
||||
from metadata_resolver import normalize_genre
|
||||
assert normalize_genre("rhythm and blues") == "R&B"
|
||||
assert normalize_genre("rock and roll") == "Rock 'n' Roll"
|
||||
return "English variants normalized correctly"
|
||||
|
||||
|
||||
def test_genre_normalize_titlecase() -> str:
|
||||
from metadata_resolver import normalize_genre
|
||||
assert normalize_genre("JAZZ") == "Jazz", f"got: {normalize_genre('JAZZ')!r}"
|
||||
assert normalize_genre("folk") == "Folk", f"got: {normalize_genre('folk')!r}"
|
||||
assert normalize_genre("Big Band") == "Big Band" # unchanged
|
||||
return "Titlecase normalization OK"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# _is_classical() Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_is_classical_by_genre() -> str:
|
||||
from executor import _is_classical
|
||||
assert _is_classical("Gardiner", "Bach", "Classical"), "Classical genre should trigger"
|
||||
assert _is_classical("Herreweghe", "Handel", "Baroque"), "Baroque should trigger"
|
||||
return "genre-based detection OK"
|
||||
|
||||
|
||||
def test_is_classical_by_composer() -> str:
|
||||
from executor import _is_classical
|
||||
assert _is_classical("Gardiner", "Bach", ""), "Bach as track_artist should trigger"
|
||||
assert _is_classical("Hurford", "beethoven", ""), "beethoven should trigger"
|
||||
return "composer-name detection OK"
|
||||
|
||||
|
||||
def test_is_classical_false_for_pop() -> str:
|
||||
from executor import _is_classical
|
||||
assert not _is_classical("Trini Lopez", "Trini Lopez", "Pop"), "same artist = not classical"
|
||||
assert not _is_classical("ABBA", "ABBA", "Pop"), "ABBA is not classical"
|
||||
assert not _is_classical("Trini Lopez", "", "R&B"), "empty track_artist = not classical"
|
||||
return "pop albums correctly not classical"
|
||||
|
||||
|
||||
def test_is_classical_false_for_folk() -> str:
|
||||
from executor import _is_classical
|
||||
assert not _is_classical("Tufaranka", "Tufaranka", "Folk"), "Folk is not classical"
|
||||
return "Folk correctly not classical"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# cover normalize Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_normalize_cover_renames_front_jpg() -> str:
|
||||
from cover_handler import normalize_cover_to_folder_jpg
|
||||
import tempfile, shutil
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
root = Path(tmpdir)
|
||||
front = root / "Front.jpg"
|
||||
front.write_bytes(b"\xff\xd8" + b"\x00" * 200)
|
||||
result = normalize_cover_to_folder_jpg(front)
|
||||
assert result.name == "folder.jpg", f"expected folder.jpg, got {result.name!r}"
|
||||
assert (root / "folder.jpg").exists(), "folder.jpg should exist"
|
||||
assert not front.exists(), "Front.jpg should be gone"
|
||||
return "Front.jpg → folder.jpg rename OK"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# executor Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -252,6 +386,19 @@ def main() -> None:
|
|||
("UNIT_15_proposed_filename_single_disc", test_proposed_filename_single_disc),
|
||||
("UNIT_16_proposed_filename_multi_disc", test_proposed_filename_multi_disc),
|
||||
("UNIT_17_proposed_filename_sanitizes_chars", test_proposed_filename_sanitizes_chars),
|
||||
# Neue Tests
|
||||
("UNIT_18_vertical_tracklist_basic", test_vertical_tracklist_basic),
|
||||
("UNIT_19_vertical_tracklist_no_duration", test_vertical_tracklist_without_duration),
|
||||
("UNIT_20_vertical_tracklist_no_false_pos", test_vertical_tracklist_not_triggered_for_normal),
|
||||
("UNIT_21_single_cd_tracklist_match", test_single_cd_tracklist_match),
|
||||
("UNIT_22_genre_normalize_german", test_genre_normalize_german),
|
||||
("UNIT_23_genre_normalize_english", test_genre_normalize_english_variants),
|
||||
("UNIT_24_genre_normalize_titlecase", test_genre_normalize_titlecase),
|
||||
("UNIT_25_is_classical_by_genre", test_is_classical_by_genre),
|
||||
("UNIT_26_is_classical_by_composer", test_is_classical_by_composer),
|
||||
("UNIT_27_is_classical_false_pop", test_is_classical_false_for_pop),
|
||||
("UNIT_28_is_classical_false_folk", test_is_classical_false_for_folk),
|
||||
("UNIT_29_normalize_cover_renames", test_normalize_cover_renames_front_jpg),
|
||||
]
|
||||
|
||||
for test_id, fn in cases:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue