From e80f43be86b73b925903b3d39c75b0941d4f7b89 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 21 Jun 2026 15:59:40 +0000 Subject: [PATCH 1/2] Add test coverage for ChordAnalyzer deduplication and edge cases --- services/analysis-engine/tests/test_chords.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/services/analysis-engine/tests/test_chords.py b/services/analysis-engine/tests/test_chords.py index 48b79e35..2d019a07 100644 --- a/services/analysis-engine/tests/test_chords.py +++ b/services/analysis-engine/tests/test_chords.py @@ -401,3 +401,61 @@ def test_chord_analyzer_all_n_chords_returns_empty() -> None: ) summary = result["sections"][0] assert summary["chords"] == [] + +def test_chord_analyzer_deduplicates_user_chords() -> None: + """Test analyzer deduplicates identical user-sourced chords within a section.""" + analyzer = ChordAnalyzer() + sections = [{"id": "verse-1"}] + roles_by_section = { + "verse-1": [ + {"harmony": {"chord": "Am", "functionLabel": "vi", "source": "user"}}, + {"harmony": {"chord": "Am", "functionLabel": "vi repeated", "source": "user"}}, + ] + } + result = analyzer.analyze(sections, roles_by_section) + assert len(result["sections"][0]["chords"]) == 1 + assert result["sections"][0]["chords"][0]["chord"] == "Am" + + +def test_chord_analyzer_deduplicates_recognized_chords() -> None: + """Test analyzer deduplicates identical recognized chords within a section.""" + analyzer = ChordAnalyzer() + sections = [{"id": "verse-1"}] + sr = 22050 + t = np.linspace(0, 2, sr * 2, endpoint=False) + other_stem = np.sin(2 * np.pi * 261.63 * t).astype(np.float32) + + recognized = [ + {"start_time": 0.0, "end_time": 1.0, "chord": "C", "confidence": "high"}, + {"start_time": 1.0, "end_time": 2.0, "chord": "C", "confidence": "high"}, + ] + + with patch.object(analyzer._recognizer, "recognize", return_value=recognized): + result = analyzer.analyze( + sections, + audio_stems={"other": other_stem}, + sample_rate=sr, + ) + + assert len(result["sections"][0]["chords"]) == 1 + assert result["sections"][0]["chords"][0]["chord"] == "C" + + + +def test_chord_analyzer_confidence_fallthrough_all_n() -> None: + """Test analyzer falls through to medium confidence when recognized chords are all N.""" + analyzer = ChordAnalyzer() + + # Setup inputs for _compute_section_confidence directly + chords = [{"chord": "C", "functionLabel": "", "source": "model"}] + recognized_chords = [{"start_time": 0.0, "end_time": 1.0, "chord": "N", "confidence": "high"}] + user_chords = [] + + confidence_level, confidence_source = analyzer._compute_section_confidence( + chords=chords, + recognized_chords=recognized_chords, + user_chords=user_chords, + ) + + assert confidence_level == "medium" + assert confidence_source == "model" From eadef3397be32e2c2728d65378406de92a076381 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 21 Jun 2026 16:36:09 +0000 Subject: [PATCH 2/2] Add test coverage for ChordAnalyzer deduplication and edge cases --- services/analysis-engine/tests/test_chords.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/analysis-engine/tests/test_chords.py b/services/analysis-engine/tests/test_chords.py index 2d019a07..e2bae518 100644 --- a/services/analysis-engine/tests/test_chords.py +++ b/services/analysis-engine/tests/test_chords.py @@ -402,6 +402,7 @@ def test_chord_analyzer_all_n_chords_returns_empty() -> None: summary = result["sections"][0] assert summary["chords"] == [] + def test_chord_analyzer_deduplicates_user_chords() -> None: """Test analyzer deduplicates identical user-sourced chords within a section.""" analyzer = ChordAnalyzer() @@ -441,7 +442,6 @@ def test_chord_analyzer_deduplicates_recognized_chords() -> None: assert result["sections"][0]["chords"][0]["chord"] == "C" - def test_chord_analyzer_confidence_fallthrough_all_n() -> None: """Test analyzer falls through to medium confidence when recognized chords are all N.""" analyzer = ChordAnalyzer()