Spaces:
Runtime error
Runtime error
Arthur_Diaz
feat(dictation): word-level dictation scoring with tolerant normalization (#8)
f6bff07 unverified | import pytest | |
| from tutor.services.dictation import normalize_words, score_dictation | |
| def test_normalize_folds_case_punctuation_contractions_spelling() -> None: | |
| assert normalize_words("Hello, World!") == ["hello", "world"] | |
| assert normalize_words("I don't know") == ["i", "do", "not", "know"] | |
| assert normalize_words("The colour of the centre") == ["the", "color", "of", "the", "center"] | |
| def test_perfect_despite_legitimate_variants() -> None: | |
| result = score_dictation("I don't like the colour.", "I do not like the color") | |
| assert result.is_perfect | |
| assert result.wer == 0.0 | |
| assert result.substitutions == result.deletions == result.insertions == 0 | |
| def test_catches_phonetic_confusion() -> None: | |
| result = score_dictation("I saw a sheep on the hill", "I saw a ship on the hill") | |
| assert result.substitutions == 1 | |
| subs = [(op.ref_word, op.hyp_word) for op in result.ops if op.op == "substitute"] | |
| assert subs == [("sheep", "ship")] | |
| def test_deletion_and_alignment_order() -> None: | |
| result = score_dictation("the quick brown fox jumps", "the quik brown fox") | |
| assert result.substitutions == 1 # quick/quik | |
| assert result.deletions == 1 # jumps missing | |
| assert [op.op for op in result.ops] == ["equal", "substitute", "equal", "equal", "delete"] | |
| def test_insertion_is_flagged() -> None: | |
| result = score_dictation("the cat sat", "the big cat sat") | |
| assert result.insertions == 1 | |
| inserted = [op.hyp_word for op in result.ops if op.op == "insert"] | |
| assert inserted == ["big"] | |
| def test_empty_hypothesis_is_all_deletions() -> None: | |
| result = score_dictation("hello world", " ") | |
| assert result.wer == 1.0 | |
| assert result.deletions == 2 | |
| assert all(op.op == "delete" for op in result.ops) | |
| def test_empty_reference_raises() -> None: | |
| with pytest.raises(ValueError, match="reference is empty"): | |
| score_dictation("!!!", "anything") | |
| def test_render_feedback_marks_errors() -> None: | |
| from tutor.app.main import render_dictation_feedback | |
| perfect = render_dictation_feedback(score_dictation("the cat sat", "the cat sat")) | |
| assert "100% correct ๐" in perfect | |
| marked = render_dictation_feedback(score_dictation("I saw a sheep", "I saw a ship")) | |
| assert "**sheep**" in marked # correct word in bold | |
| assert "~~ship~~" in marked # learner's wrong version struck through | |