Files
ewoooc/tests/test_competitor_match_attempts_persistence.py
OoO 032ba2bbd3
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
縮短 PChome feeder 外部請求 timeout
2026-05-19 23:23:48 +08:00

128 lines
4.5 KiB
Python

from pathlib import Path
import logging
from datetime import datetime
ROOT = Path(__file__).resolve().parents[1]
def test_competitor_feeder_persists_all_match_attempt_outcomes():
source = (ROOT / "services/competitor_price_feeder.py").read_text(encoding="utf-8")
migration = (ROOT / "migrations/023_competitor_match_attempts.sql").read_text(encoding="utf-8")
assert "attempts_written" in source
assert "_ensure_competitor_match_attempts_table" in source
assert "_record_match_attempt" in source
assert "INSERT INTO competitor_match_attempts" in source
assert "CAST(:search_terms AS jsonb)" in source
assert 'attempt_status="matched"' in source
assert 'attempt_status="low_score"' in source
assert 'attempt_status="no_result"' in source
assert 'attempt_status="no_match"' in source
assert 'attempt_status="error"' in source
assert "_search_pchome_candidates(crawler, momo_name, search_terms, momo_price=momo_price)" in source
assert 'attempt_status="needs_review"' in source
assert "_should_upsert_competitor_price" in source
assert "replace_legacy_unverified" in source
assert "identity_v2" in source
assert "_fetch_expired_identity_skus" in source
assert "run_expired_identity_refresh" in source
assert "refresh_known_identity" in source
assert 'PCHOME_FEEDER_TIMEOUT", "12"' in source
assert "PChomeCrawler(timeout=REQUEST_TIMEOUT" in source
assert "CREATE TABLE IF NOT EXISTS competitor_match_attempts" in migration
assert "attempt_status" in migration
assert "search_terms" in migration
assert "best_match_score" in migration
assert "error_message" in migration
assert "idx_comp_match_attempts_sku_source_time" in migration
def test_competitor_feeder_logs_keyword_parser_fallback(monkeypatch, caplog):
from services import competitor_price_feeder
from services import marketplace_product_matcher
def broken_build_search_terms(*_args, **_kwargs):
raise RuntimeError("matcher unavailable")
monkeypatch.setattr(marketplace_product_matcher, "build_search_terms", broken_build_search_terms)
caplog.set_level(logging.DEBUG, logger="services.competitor_price_feeder")
terms = competitor_price_feeder._build_search_keywords("理膚寶水 B5 修復霜 40ml")
assert terms
assert "fallback to cleaned product name" in caplog.text
def test_competitor_feeder_refreshes_expired_identity_by_known_product_id(monkeypatch):
from services.competitor_price_feeder import CompetitorPriceFeeder
from services.pchome_crawler import PChomeProduct
requested = []
product = PChomeProduct(
product_id="DDAB01-1900ABCD",
name="舒特膚 AD 乳液 200ml",
price=899,
original_price=999,
discount=10,
image_url="",
product_url="https://24h.pchome.com.tw/prod/DDAB01-1900ABCD",
stock=50,
store="24h",
rating=4.8,
review_count=12,
is_on_sale=True,
crawled_at=datetime.now(),
)
class FakeCrawler:
def __init__(self, *_args, **_kwargs):
pass
def fetch_product_details(self, product_ids, batch_size=20):
requested.extend(product_ids)
return True, "ok", [product]
monkeypatch.setattr("services.pchome_crawler.PChomeCrawler", FakeCrawler)
feeder = CompetitorPriceFeeder(engine=object())
writes = []
attempts = []
monkeypatch.setattr(
feeder,
"_should_upsert_competitor_price",
lambda *_args, **_kwargs: (True, "same_or_empty_existing"),
)
monkeypatch.setattr(
feeder,
"_upsert_competitor_price",
lambda sku, product, score, tags, **kwargs: writes.append({
"sku": sku,
"product_id": product.product_id,
"score": score,
"tags": tags,
**kwargs,
}),
)
monkeypatch.setattr(
feeder,
"_record_match_attempt",
lambda *args, **kwargs: attempts.append(kwargs),
)
result = feeder._run_known_identity_refresh_items([{
"sku": "A001",
"name": "舒特膚 AD 乳液 200ml",
"product_id": 1,
"momo_price": 980,
"competitor_product_id": "DDAB01-1900ABCD",
}])
assert requested == ["DDAB01-1900ABCD"]
assert result.matched == 1
assert writes[0]["product_id"] == "DDAB01-1900ABCD"
assert "identity_v2" in writes[0]["tags"]
assert "refresh_known_identity" in writes[0]["tags"]
assert attempts[0]["attempt_status"] == "matched"
assert attempts[0]["search_terms"] == ["known_product_id:DDAB01-1900ABCD"]