"""Юнит-тесты скоринга плагиата (итоговый процент, который видит студент).""" from app.scoring import aggregate_results def _m(title: str, pos: int) -> dict: return {"source_title": title, "position_start": pos} def test_empty_input_is_zero(): out = aggregate_results([], [], [], total_fragments=10) assert out["overall_similarity"] == 0.0 assert out["flagged_fragments"] == 0 assert out["matches"] == [] assert out["by_method"] == {"exact": 0, "fuzzy": 0, "semantic_llm": 0} def test_zero_fragments_does_not_divide_by_zero(): out = aggregate_results([_m("A", 0)], [], [], total_fragments=0) assert out["overall_similarity"] == 0.0 def test_percentage_is_share_of_flagged_positions(): # 2 из 4 фрагментов помечены → 50% level1 = [_m("A", 0), _m("B", 5)] out = aggregate_results(level1, [], [], total_fragments=4) assert out["overall_similarity"] == 50.0 assert out["flagged_fragments"] == 2 def test_same_position_multiple_sources_counts_once(): # Одна позиция совпала с двумя разными источниками — доля не раздувается level1 = [_m("A", 0)] semantic = [_m("B", 0)] # та же позиция 0, другой источник out = aggregate_results(level1, [], semantic, total_fragments=2) assert out["flagged_fragments"] == 1 assert out["overall_similarity"] == 50.0 # оба совпадения сохранены в matches (дедуп только по паре title:pos) assert len(out["matches"]) == 2 def test_exact_duplicate_match_is_deduplicated(): # Один и тот же источник в одной позиции пришёл дважды — остаётся один dup = _m("A", 3) out = aggregate_results([dict(dup)], [dict(dup)], [], total_fragments=5) assert len(out["matches"]) == 1 def test_similarity_capped_at_100(): # Больше уникальных позиций, чем фрагментов (пограничный случай) → не выше 100% matches = [_m(f"S{i}", i) for i in range(5)] out = aggregate_results(matches, [], [], total_fragments=3) assert out["overall_similarity"] == 100.0 def test_by_method_counts_raw_matches_per_level(): out = aggregate_results( [_m("A", 0), _m("B", 1)], # exact = 2 [_m("C", 2)], # fuzzy = 1 [_m("D", 3), _m("E", 4), _m("F", 5)], # semantic_llm = 3 total_fragments=10, ) assert out["by_method"] == {"exact": 2, "fuzzy": 1, "semantic_llm": 3} def test_percentage_rounded_to_two_decimals(): # 1 из 3 → 33.333... → 33.33 out = aggregate_results([_m("A", 0)], [], [], total_fragments=3) assert out["overall_similarity"] == 33.33