DealDocumentScreening/tests/unit/test_prescreen_extractor.py
2026-08-17 20:49:29 +03:00

113 lines
4.6 KiB
Python
Raw Permalink 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.

"""Unit tests for the deterministic regex prescreen extractor."""
from __future__ import annotations
import pytest
from contract_check.worker_prescreen.extractor import extract_contract_meta
SIMPLE_SUPPLY = """\
ДОГОВОР ПОСТАВКИ № 42
г. Москва
Общество с ограниченной ответственностью «Продавец»,
именуемое в дальнейшем «Поставщик», в лице директора Иванова И.И.,
с одной стороны, и
Общество с ограниченной ответственностью «Покупатель»,
именуемое в дальнейшем «Покупатель», с другой стороны,
заключили настоящий договор о нижеследующем.
1. Предмет договора
Поставщик обязуется передать в собственность Покупателю товар.
2. Цена и порядок расчётов
2.1. Общая стоимость товара составляет 1 250 000 (один миллион двести пятьдесят тысяч) рублей.
3. Срок действия договора
3.1. Настоящий договор вступает в силу с 01.09.2025 и действует по 31.08.2026.
4. Ответственность сторон
4.1. За просрочку поставки Поставщик уплачивает неустойку в размере 0,1% от стоимости.
5. Порядок разрешения споров
5.1. Споры подлежат рассмотрению в Арбитражном суде г. Москвы.
"""
MINIMAL = """\
Договор оказания услуг между ИП Петров Петр Петрович и ООО «Клиент».
Стоимость услуг составляет 50 000 рублей.
"""
def test_supply_extraction() -> None:
meta = extract_contract_meta(SIMPLE_SUPPLY)
assert meta.contract_type == "supply"
assert "Продавец" in (meta.party_a or "")
assert "Покупатель" in (meta.party_b or "")
assert meta.total_amount == 1250000.0
assert meta.currency == "RUB"
assert meta.start_date == "2025-09-01"
assert meta.end_date == "2026-08-31"
assert meta.has_penalty_clause is True
assert meta.has_termination_clause is False
assert meta.has_arbitration is True
assert meta.confidence_score > 0.6
def test_minimal_extraction() -> None:
meta = extract_contract_meta(MINIMAL)
assert meta.contract_type == "services"
assert "ИП Петров" in (meta.party_a or "")
assert "ООО «Клиент»" in (meta.party_b or "")
assert meta.total_amount == 50000.0
assert meta.currency == "RUB"
def test_confidence_score_bounds() -> None:
meta = extract_contract_meta("")
assert meta.confidence_score == 0.0
assert 0.0 <= meta.confidence_score <= 1.0
def test_party_extraction_handles_whitespace() -> None:
text = "Договор между ООО «Альфа» и ООО «Бета»"
meta = extract_contract_meta(text)
assert "Альфа" in (meta.party_a or "")
assert "Бета" in (meta.party_b or "")
@pytest.mark.parametrize(
("clause", "expected"),
[
("Стороны вправе расторгнуть договор в одностороннем порядке", "has_termination_clause"),
("В случае нарушения Покупатель уплачивает штраф", "has_penalty_clause"),
("Споры рассматриваются в Арбитражном суде", "has_arbitration"),
],
)
def test_boolean_flags(clause: str, expected: str) -> None:
meta = extract_contract_meta(f"Договор поставки. {clause}.")
assert getattr(meta, expected) is True
def test_shim_defaults_to_heuristic_v2() -> None:
meta = extract_contract_meta(SIMPLE_SUPPLY)
assert meta.confidence_score > 0.6
def test_keep_regex_flag_routes_to_regex_v1(monkeypatch: pytest.MonkeyPatch) -> None:
"""PRESCREEN_KEEP_REGEX=true keeps the legacy regex path alive (plan §5)."""
from contract_check.worker_prescreen.extractor import _extract_contract_meta_regex
monkeypatch.setenv("PRESCREEN_KEEP_REGEX", "true")
meta = extract_contract_meta(SIMPLE_SUPPLY)
legacy = _extract_contract_meta_regex(SIMPLE_SUPPLY.replace("\n", " "))
# Identical extraction semantics on the ported fixtures.
assert meta.model_dump() == legacy.model_dump()
monkeypatch.setenv("PRESCREEN_KEEP_REGEX", "false")
assert extract_contract_meta(SIMPLE_SUPPLY).model_dump() == meta.model_dump()