"""Юнит-тесты алгоритма Winnowing (уровень 1 — точные/частичные совпадения).""" from app.algorithms.winnowing import ( compute_similarity, get_ngrams, hash_ngram, jaccard_similarity, winnow, ) # Достаточно длинный текст, чтобы окно Winnowing реально отработало LONG = ( "машинное обучение позволяет извлекать закономерности из больших объёмов " "данных без явного программирования каждого правила вручную аналитиком" ) def test_get_ngrams_basic(): assert get_ngrams(["a", "b", "c", "d"], k=2) == ["a b", "b c", "c d"] def test_get_ngrams_too_short_is_empty(): assert get_ngrams(["a", "b"], k=5) == [] def test_hash_ngram_is_deterministic(): assert hash_ngram("одна и та же строка") == hash_ngram("одна и та же строка") def test_hash_ngram_fits_signed_int64(): # Хэш обязан умещаться в PostgreSQL BIGINT (signed 64-bit) for s in ("a", "тест", "one two three four five", "𝔘𝔫𝔦𝔠𝔬𝔡𝔢"): h = hash_ngram(s) assert -(2**63) <= h <= 2**63 - 1 def test_winnow_short_text_is_empty(): assert winnow("три слова тут", k=5) == set() def test_winnow_identical_text_identical_fingerprint(): assert winnow(LONG) == winnow(LONG) def test_winnow_is_case_insensitive(): assert winnow(LONG) == winnow(LONG.upper()) def test_jaccard_identical_is_one(): fp = winnow(LONG) assert fp # непустой отпечаток assert jaccard_similarity(fp, fp) == 1.0 def test_jaccard_disjoint_is_zero(): assert jaccard_similarity({1, 2, 3}, {4, 5, 6}) == 0.0 def test_jaccard_empty_is_zero(): assert jaccard_similarity(set(), {1, 2}) == 0.0 def test_compute_similarity_identical_documents_is_one(): # Ключевая гарантия L1: копия документа детектится как 100% совпадение assert compute_similarity(LONG, LONG) == 1.0 def test_compute_similarity_unrelated_documents_is_low(): other = ( "рецепт домашнего хлеба на закваске требует терпения муки воды соли " "и тёплого места для медленного подъёма теста в течение ночи" ) assert compute_similarity(LONG, other) < 0.1 def test_compute_similarity_partial_overlap_is_between(): modified = LONG + " добавлен ещё один совершенно новый хвост предложения здесь" sim = compute_similarity(LONG, modified) assert 0.0 < sim < 1.0