Files
test-search-engine/tests/test_matcher.py
T

198 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import pytest
from app.matcher import CatalogMatcher
@pytest.mark.parametrize(
("message", "sku"),
[
("дрель ударная prowerk pw-750 в наличии?", "INS-0008"),
("кабель шввп 2х0.5 сколько за метр", "KAB-0017"),
("диск пильный 190 на 48 зубьев", "DSK-0034"),
("уровень 1000 мм есть?", "RIN-0024"),
("гайки м10 нужны", "KRP-0020"),
("лента фум 12 мм", "RAS-0060"),
("перчатки нитриловые есть?", "PER-0002"),
("проф труба 20х20 стенка полтора", "TRB-0002"),
("гкл 9.5 сколько лист", "GKL-0001"),
("хомуты пластиковые 4.8х400", "RAS-0014"),
("сдс бур 6 на 110", "BIT-0074"),
("наждачка р120 листами", "RAS-0050"),
("круг зачистной на 125", "DSK-0018"),
("бита ph2 50 мм", "BIT-0005"),
("саморезы по дереву 3.5х45 пачка 200", "SAM-0010"),
("труба профильная 20х20х2", "TRB-0003"),
("ввгнг лс 3х1.5", "KAB-0010"),
("диск отрезной по металлу 115х1.2", "DSK-0002"),
("бур sds 10х210", "BIT-0080"),
("дюбель-гвоздь 6х60", "KRP-0048"),
],
)
def test_unique_queries_are_matched(
matcher: CatalogMatcher, message: str, sku: str
) -> None:
result = matcher.match(message)
assert result.status == "matched"
assert [candidate.sku for candidate in result.candidates] == [sku]
assert 0.0 <= result.candidates[0].confidence <= 1.0
@pytest.mark.parametrize(
"message",
[
"саморезы по металлу 4.2х70",
"труба профильная 35х35",
"кабель ввгнг 4х2.5",
"ушм на 150",
"бита t50",
"шпилька м16 метровая",
"бур 10х220",
"бита ph2 70 мм",
],
)
def test_explicit_attribute_conflicts_are_not_found(
matcher: CatalogMatcher, message: str
) -> None:
result = matcher.match(message)
assert result.status == "not_found"
assert result.candidates == []
@pytest.mark.parametrize(
"message",
[
"нужен кабель",
"дайте дюбелей",
"сверло нужно",
"какие есть диски",
"перфоратор посоветуйте",
"шуруповерт как у макиты, только дешевле",
"шурик на 12в недорогой",
"болгарка на 230 какая есть",
"гкл 12.5",
],
)
def test_under_specified_product_queries_are_ambiguous(
matcher: CatalogMatcher, message: str
) -> None:
result = matcher.match(message)
assert result.status == "ambiguous"
assert 2 <= len(result.candidates) <= 3
def test_unspecified_packaging_remains_ambiguous(matcher: CatalogMatcher) -> None:
result = matcher.match("здравствуйте, есть саморезы гкл 3.5х25?")
assert result.status == "ambiguous"
assert {candidate.sku for candidate in result.candidates} == {
"SAM-0061",
"SAM-0062",
"SAM-0063",
}
def test_package_word_filters_out_kilogram_item(matcher: CatalogMatcher) -> None:
result = matcher.match("саморезы по дереву 4.2 на 75, пачку")
assert result.status == "ambiguous"
assert {candidate.sku for candidate in result.candidates} == {
"SAM-0022",
"SAM-0023",
}
@pytest.mark.parametrize(
"message",
[
"здравствуйте, вы до скольки работаете?",
"можно оплатить картой при получении?",
"где находится ваш магазин",
"статус заказа 4512 подскажите",
"спасибо, заказ получил, все отлично",
"",
],
)
def test_non_product_messages_are_not_found(
matcher: CatalogMatcher, message: str
) -> None:
result = matcher.match(message)
assert result.status == "not_found"
assert result.candidates == []
def test_product_evidence_has_priority_over_service_words(matcher: CatalogMatcher) -> None:
result = matcher.match("статус заказа 4512 и еще нужен бур 8х160")
assert result.status == "matched"
assert result.candidates[0].sku == "BIT-0077"
@pytest.mark.parametrize("brand", ["makita", "макита", "макиты", "макиту"])
def test_makita_transliterations_share_the_same_brand_alias(
matcher: CatalogMatcher, brand: str
) -> None:
result = matcher.match(f"шуруповерт как у {brand}, только дешевле")
assert result.status == "ambiguous"
assert [candidate.sku for candidate in result.candidates] == [
"INS-0017",
"INS-0010",
"INS-0003",
]
def test_cheap_preference_orders_candidates_by_ascending_price(
matcher: CatalogMatcher,
) -> None:
result = matcher.match("шуруповерт как у макиты, только дешевле")
prices_by_sku = {item.sku: item.price for item in matcher.items}
candidate_prices = [
prices_by_sku[candidate.sku] for candidate in result.candidates
]
assert candidate_prices == sorted(candidate_prices)
@pytest.mark.parametrize(
"brand", ["ToolKraft", "toolkraft", "тулкрафт", "тул крафт"]
)
def test_brand_only_toolkraft_query_returns_catalog_items(
matcher: CatalogMatcher, brand: str
) -> None:
result = matcher.match(brand)
assert result.status == "ambiguous"
assert [candidate.sku for candidate in result.candidates] == [
"INS-0022",
"INS-0023",
"INS-0024",
]
def test_unknown_toolkraft_model_does_not_fall_back_to_brand_results(
matcher: CatalogMatcher,
) -> None:
result = matcher.match("ToolKraft TK-999")
assert result.status == "not_found"
assert result.candidates == []
@pytest.mark.parametrize("query", ["шурпуоверт на 12в", "шураыввавёрт на 12в"])
def test_product_type_survives_typos(matcher: CatalogMatcher, query: str) -> None:
result = matcher.match(query)
assert result.status == "ambiguous"
assert all(candidate.sku.startswith("INS-") for candidate in result.candidates)
def test_bare_size_is_parsed_without_unit(matcher: CatalogMatcher) -> None:
assert matcher.match("бита ph2 50").candidates[0].sku == "BIT-0005"
assert matcher.match("диск пильный 190 48 зубьев").candidates[0].sku == "DSK-0034"
def test_unknown_size_does_not_fall_back_to_nearest_product(
matcher: CatalogMatcher,
) -> None:
result = matcher.match("ушм 150")
assert result.status == "not_found"
assert result.candidates == []