133 lines
4.7 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.

import json
import httpx
import pytest
from app.schemas.ocr import OcrMeasurement
from app.services.baidu_ocr import BaiduOcrClient
from app.services.ocr import OcrService
@pytest.mark.asyncio
async def test_webimage_recognition_returns_text_and_confidence() -> None:
def handler(request: httpx.Request) -> httpx.Response:
if request.url.path.endswith("/token"):
return httpx.Response(200, json={"access_token": "token", "expires_in": 3600})
assert request.url.path.endswith("/webimage")
return httpx.Response(
200,
json={
"words_result": [
{"words": "产品名称:测试面霜", "probability": {"average": 0.92}},
{"words": "pH:5.6", "probability": {"average": 0.88}},
]
},
)
client = BaiduOcrClient(httpx.MockTransport(handler))
client.api_key = "api-key"
client.secret_key = "secret-key"
text, confidence, pages = await client.recognize_image(b"fake-image")
assert text == "产品名称:测试面霜\npH:5.6"
assert confidence == pytest.approx(0.9)
assert pages == 1
@pytest.mark.asyncio
async def test_paddle_document_recognition_polls_and_downloads_result() -> None:
calls = {"query": 0}
def handler(request: httpx.Request) -> httpx.Response:
if request.url.path.endswith("/token"):
return httpx.Response(200, json={"access_token": "token", "expires_in": 3600})
if request.url.path.endswith("/task/query"):
calls["query"] += 1
status = "processing" if calls["query"] == 1 else "success"
result = {"status": status}
if status == "success":
result["parse_result_url"] = "https://mock.bcebos.com/result.json"
return httpx.Response(200, json={"error_code": 0, "result": result})
if request.url.path.endswith("/task"):
return httpx.Response(200, json={"error_code": 0, "result": {"task_id": "task-1"}})
if request.url.path.endswith("/result.json"):
return httpx.Response(
200,
content=json.dumps(
{
"pages": [
{
"text": "产品名称:测试面霜",
"tables": [{"markdown": "|检测项|值|\n|pH|5.6|"}],
}
]
},
ensure_ascii=False,
).encode(),
)
raise AssertionError(f"unexpected URL: {request.url}")
client = BaiduOcrClient(httpx.MockTransport(handler))
client.api_key = "api-key"
client.secret_key = "secret-key"
client.poll_interval = 0.001
text, confidence, pages = await client.recognize_document(b"%PDF-test", "report.pdf")
assert "测试面霜" in text
assert "|pH|5.6|" in text
assert confidence is None
assert pages == 1
assert calls["query"] == 2
@pytest.mark.parametrize(
("raw_value", "value", "standard", "expected"),
[
("5.6", 5.6, "pH 4.5-6.5", "合格"),
("3.8", 3.8, "色差 ΔE≤3.0", "不合格"),
("+18%", 18, "喷出量偏差≤±15%", "不合格"),
("0.9 N·m", 0.9, "开启力矩 0.8~3.2N·m", "合格"),
],
)
def test_standard_numeric_evaluation(raw_value: str, value: float, standard: str, expected: str) -> None:
measurement = OcrMeasurement(
item="检测项",
raw_value=raw_value,
value=value,
confidence=0.95,
needs_review=False,
)
result, reason = OcrService.evaluate_standard(measurement, standard)
assert result == expected
assert reason is None
def test_upload_type_is_detected_from_content_not_filename() -> None:
assert OcrService._detect_type(b"%PDF-1.7") == ("application/pdf", ".pdf")
assert OcrService._detect_type(b"\x89PNG\r\n\x1a\nrest") == ("image/png", ".png")
assert OcrService._detect_type(b"\xff\xd8\xffrest") == ("image/jpeg", ".jpg")
def test_standard_judgment_rejects_unit_mismatch() -> None:
measurement = OcrMeasurement(
item="铅含量",
raw_value="8mg/L",
value=8,
unit="mg/L",
confidence=0.95,
needs_review=False,
)
result, reason = OcrService.evaluate_standard(measurement, "铅≤10mg/kg")
assert result == "待人工确认"
assert reason == "检测值单位 mg/L 与标准单位 mg/kg 不一致"
def test_generic_quantity_does_not_fuzzy_match_a_standard() -> None:
class Rule:
risk_point = "销售包装可视面及最小销售单元完整标注"
judge_standard = "中英文标签内容完整"
assert OcrService._best_rule("数量", [Rule()]) is None