From 03c54910c287faef5670b589c491658b138316f5 Mon Sep 17 00:00:00 2001 From: Luis Raimundo Date: Sun, 7 Jun 2026 19:04:44 +0100 Subject: [PATCH] Add MusicXML onset verticality tests --- ...musicxml_onset_verticalities_additional.py | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 tests/test_musicxml_onset_verticalities_additional.py diff --git a/tests/test_musicxml_onset_verticalities_additional.py b/tests/test_musicxml_onset_verticalities_additional.py new file mode 100644 index 0000000..f4c4660 --- /dev/null +++ b/tests/test_musicxml_onset_verticalities_additional.py @@ -0,0 +1,108 @@ +"""Focused tests for ``iav.musicxml_io._onset_verticalities`` uncovered branches.""" + +from __future__ import annotations + +import pytest + +from iav.musicxml_io._onset_verticalities import ( + parse_musicxml_verticalities_bytes, + parse_musicxml_verticalities_bytes_with_sounding_transpose, +) + + +def _score(body: str) -> bytes: + return ( + '' + f'{body}' + ).encode("utf-8") + + +def _measure(inner: str, *, attributes: str = "1") -> str: + return f'{attributes}{inner}' + + +def _note(step: str, octave: int, *, duration: int = 1) -> str: + return ( + f"{step}{octave}" + f"{duration}" + ) + + +def test_parse_onset_verticalities_when_get_musicxml_bytes_none(monkeypatch): + monkeypatch.setattr( + "iav.musicxml_io._onset_verticalities.get_musicxml_bytes", + lambda _b: None, + ) + slices, skipped = parse_musicxml_verticalities_bytes( + b"ignored", + include_grace=False, + include_cue=False, + ) + assert slices == [] + assert skipped == 0 + + +def test_transpose_wrapper_passes_apply_musicxml_transpose_true(monkeypatch): + captured: dict = {} + + def _capture_impl(file_bytes, include_grace, include_cue, *, apply_musicxml_transpose): + captured["file_bytes"] = file_bytes + captured["include_grace"] = include_grace + captured["include_cue"] = include_cue + captured["apply_musicxml_transpose"] = apply_musicxml_transpose + return [], 0 + + monkeypatch.setattr( + "iav.musicxml_io._onset_verticalities._parse_musicxml_verticalities_impl", + _capture_impl, + ) + payload = b"" + parse_musicxml_verticalities_bytes_with_sounding_transpose( + payload, + include_grace=True, + include_cue=False, + ) + assert captured == { + "file_bytes": payload, + "include_grace": True, + "include_cue": False, + "apply_musicxml_transpose": True, + } + + +def test_written_vs_sounding_onset_verticalities_differ_with_transpose(): + body = _measure( + _note("D", 4), + attributes="1-2", + ) + xml = _score(body) + written, skipped_w = parse_musicxml_verticalities_bytes( + xml, + include_grace=False, + include_cue=False, + ) + sounding, skipped_s = parse_musicxml_verticalities_bytes_with_sounding_transpose( + xml, + include_grace=False, + include_cue=False, + ) + assert skipped_w == 0 + assert skipped_s == 0 + assert len(written) == 1 + assert len(sounding) == 1 + assert written[0]["time"] == pytest.approx(0.0) + assert sounding[0]["time"] == pytest.approx(0.0) + assert written[0]["notes"] == [("D", 0.0, 4)] + assert sounding[0]["notes"] == [("C", 0.0, 4)] + + +def test_non_transposed_baseline_matches_written_pitch_only(): + body = _measure(_note("E", 4)) + xml = _score(body) + written, _ = parse_musicxml_verticalities_bytes(xml, include_grace=False, include_cue=False) + sounding, _ = parse_musicxml_verticalities_bytes_with_sounding_transpose( + xml, + include_grace=False, + include_cue=False, + ) + assert written == sounding == [{"time": 0.0, "notes": [("E", 0.0, 4)]}]