Classify static and smart crates
This commit is contained in:
@@ -123,6 +123,7 @@ def test_analyze_prints_health_without_writing_reports(tmp_path, monkeypatch, ca
|
||||
assert "Overall Health: 50.0%" in output
|
||||
assert "Tracks: 1" in output
|
||||
assert "Crate References: 2" in output
|
||||
assert "References Scored: 2" in output
|
||||
assert "Healthy References: 1" in output
|
||||
assert "Broken References: 1" in output
|
||||
assert "Unused Tracks: 0" in output
|
||||
|
||||
@@ -3,12 +3,14 @@ from pathlib import Path
|
||||
import pytest
|
||||
|
||||
from serato_doctor.crate_parser import (
|
||||
classify_crate,
|
||||
clean_path,
|
||||
load_crate,
|
||||
parse_crate,
|
||||
parse_crates,
|
||||
path_markers,
|
||||
)
|
||||
from serato_doctor.models.crate import CrateKind
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -84,3 +86,18 @@ def test_parse_crates_reuses_configured_roots_for_every_crate(tmp_path):
|
||||
"First.mp3",
|
||||
"Second.mp3",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("relative_path", "expected"),
|
||||
[
|
||||
("_Serato_/Subcrates/House.crate", CrateKind.STATIC),
|
||||
("_Serato_/Smartcrates/Warmup.crate", CrateKind.SMART),
|
||||
("_Serato_/Subcrates/Compatible by key.crate", CrateKind.SMART),
|
||||
("fixtures/Unknown.crate", CrateKind.UNKNOWN),
|
||||
],
|
||||
)
|
||||
def test_classify_crate_uses_provenance_and_known_dynamic_name(
|
||||
tmp_path, relative_path, expected
|
||||
):
|
||||
assert classify_crate(tmp_path / relative_path) is expected
|
||||
|
||||
+32
-1
@@ -1,6 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
from serato_doctor.health import analyze_health
|
||||
from serato_doctor.models.crate import Crate, CrateKind
|
||||
from serato_doctor.models.library import Library
|
||||
from serato_doctor.models.reference import TrackReference
|
||||
from serato_doctor.models.track import DiskTrack
|
||||
@@ -36,9 +37,10 @@ def test_health_report_exposes_each_metric():
|
||||
|
||||
assert report.score == 33.3
|
||||
assert report.score_basis == (
|
||||
"Resolved crate references / total crate references"
|
||||
"Resolved non-dynamic references / non-dynamic references scored"
|
||||
)
|
||||
assert report.total_references == 3
|
||||
assert report.scored_references == 3
|
||||
assert report.healthy_references == 1
|
||||
assert report.missing_references == 2
|
||||
assert report.unique_missing_filenames == 2
|
||||
@@ -54,3 +56,32 @@ def test_empty_library_has_no_health_score():
|
||||
|
||||
assert report.score is None
|
||||
assert report.total_references == 0
|
||||
assert report.scored_references == 0
|
||||
|
||||
|
||||
def test_smart_crate_references_are_reported_but_not_scored():
|
||||
static_reference = reference("Found.mp3")
|
||||
smart_reference = TrackReference(
|
||||
Path("Smartcrates/Dynamic.crate"),
|
||||
Path("/old/House/Dynamic.mp3"),
|
||||
"Dynamic.mp3",
|
||||
)
|
||||
crates = [
|
||||
Crate(Path("Subcrates/Static.crate"), (static_reference,), CrateKind.STATIC),
|
||||
Crate(
|
||||
Path("Smartcrates/Dynamic.crate"),
|
||||
(smart_reference,),
|
||||
CrateKind.SMART,
|
||||
),
|
||||
]
|
||||
library = Library.from_crates(crates, [track("Found.mp3")])
|
||||
|
||||
report = analyze_health(library)
|
||||
|
||||
assert report.score == 100.0
|
||||
assert report.total_references == 2
|
||||
assert report.scored_references == 1
|
||||
assert report.missing_references == 0
|
||||
assert report.static_crates == 1
|
||||
assert report.smart_crates == 1
|
||||
assert report.dynamic_references_excluded == 1
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import runpy
|
||||
from pathlib import Path
|
||||
|
||||
from serato_doctor.crate_parser import parse_crates
|
||||
from serato_doctor.crate_parser import load_library_crates
|
||||
from serato_doctor.models.crate import CrateKind
|
||||
from serato_doctor.models.library import Library
|
||||
from serato_doctor.scanner import scan_audio
|
||||
|
||||
@@ -13,9 +14,10 @@ def test_generated_sample_library_has_expected_scenario(tmp_path):
|
||||
build_sample = runpy.run_path(str(generator_path))["build_sample"]
|
||||
sample_root = build_sample(tmp_path / "sample")
|
||||
|
||||
references = parse_crates(sample_root / "Serato" / "_Serato_" / "Subcrates")
|
||||
crates = load_library_crates(sample_root / "Serato" / "_Serato_")
|
||||
tracks = scan_audio(sample_root / "Music")
|
||||
results = Library.build(references, tracks).reconcile_by_filename()
|
||||
library = Library.from_crates(crates, tracks)
|
||||
results = library.reconcile_by_filename()
|
||||
missing = {
|
||||
result.reference.filename
|
||||
for result in results
|
||||
@@ -23,6 +25,8 @@ def test_generated_sample_library_has_expected_scenario(tmp_path):
|
||||
}
|
||||
|
||||
assert len(list((sample_root / "Serato").rglob("*.crate"))) == 7
|
||||
assert len(references) == 13
|
||||
assert len(library.references) == 13
|
||||
assert len(tracks) == 10
|
||||
assert missing == {"Missing.mp3", "Old Name.mp3"}
|
||||
assert sum(crate.kind is CrateKind.STATIC for crate in crates) == 5
|
||||
assert sum(crate.kind is CrateKind.SMART for crate in crates) == 2
|
||||
|
||||
Reference in New Issue
Block a user