o2o-plagiarism-ai/tests/test_api.py

148 lines
5.5 KiB
Python

"""스모크 테스트. `pip install fastapi httpx pytest` 후 실행."""
from __future__ import annotations
from fastapi.testclient import TestClient
from app.main import app
def test_health():
with TestClient(app) as client:
resp = client.get("/v1/health")
assert resp.status_code == 200
body = resp.json()
assert body["status"] == "ok"
assert body["corpus_size"] >= 0
def test_detect_no_auth_required():
"""인증 제거 - 키 없이도 200 응답."""
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/detect",
json={"doc_id": "x", "text": "테스트 본문"},
)
assert resp.status_code == 200
def test_detect_returns_schema():
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/detect",
json={
"doc_id": "t-1",
"text": "어린왕자는 작은 별에서 온 소년이다. 그는 여우를 만나 길들임을 배운다.",
},
)
assert resp.status_code == 200
body = resp.json()
assert body["doc_id"] == "t-1"
assert "matches" in body
assert "extracted_elements" in body
assert "engine_version" in body
def test_copyright_review_returns_only_mobile_tab_fields():
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/review",
json={"doc_id": "mobile-1", "text": "창밖으로 보이는 숲은 오늘따라 푸르게 보였다."},
)
assert resp.status_code == 200
body = resp.json()
assert set(body) == {
"doc_id", "copyright", "similar_sentences",
"ai_generation_suspicion", "legal_judgment", "analyzed_at",
}
assert 0 <= body["copyright"]["originality_percent"] <= 100
assert body["copyright"]["description"]
assert body["similar_sentences"]["label"].endswith("건")
assert body["ai_generation_suspicion"]["label"] in {
"낮음", "중간", "높음", "확인 불가",
}
assert "matches" not in body
assert "extracted_elements" not in body
assert "score_semantics" not in body
def test_batch_flow():
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/batch",
json={
"items": [
{"doc_id": "b-1", "text": "앤 셜리는 초록 지붕 집에 입양된 소녀다."},
]
},
)
assert resp.status_code == 202
job_id = resp.json()["job_id"]
status = client.get(f"/v1/plagiarism/batch/{job_id}")
assert status.status_code == 200
def test_detect_exposes_score_semantics():
"""#9 — 점수/임계값의 의미가 응답에 명시되어야 한다."""
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/detect",
json={"doc_id": "s-1", "text": "어린왕자는 작은 별에서 온 소년이다."},
)
assert resp.status_code == 200
sem = resp.json()["score_semantics"]
assert sem["threshold_source"] == "server_default"
assert sem["threshold_calibrated"] is False
assert sem["provisional"] is True, "캘리브레이션 전에는 잠정값으로 노출"
assert 0.0 <= sem["union_coverage"] <= 1.0
assert sem["query_chars"] > 0
assert "침해 확률이 아닙니다" in sem["note"]
def test_detect_reports_request_threshold_override():
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/detect",
json={"doc_id": "s-2", "text": "앤 셜리는 초록 지붕 집에 입양된 소녀다.",
"options": {"threshold": 0.4}},
)
sem = resp.json()["score_semantics"]
assert sem["threshold_source"] == "request_override"
assert sem["threshold_used"] == 0.4
def test_detect_accepts_legal_context():
"""#10 — 사람이 확인한 사실을 전달하면 missing_factors 에서 빠진다."""
with TestClient(app) as client:
base = client.post(
"/v1/plagiarism/detect",
json={"doc_id": "l-1", "text": "홍길동은 활빈당을 만들어 재물을 나누었다."},
).json()["legal_risk"]
assert base["access_evidence"] == "not_provided"
assert len(base["missing_factors"]) == 3
supplied = client.post(
"/v1/plagiarism/detect",
json={
"doc_id": "l-2", "text": "홍길동은 활빈당을 만들어 재물을 나누었다.",
"legal_context": {
"work_type": "literary", "access_evidence": True,
"protected_expression_reviewed": True, "rights_verified": True,
},
},
).json()["legal_risk"]
assert supplied["access_evidence"] == "provided"
assert supplied["protected_expression"] == "reviewed"
assert supplied["missing_factors"] == []
def test_matches_carry_match_reasons():
with TestClient(app) as client:
resp = client.post(
"/v1/plagiarism/detect",
json={"doc_id": "r-1", "text": "어린왕자는 작은 별에서 온 소년이다. 그는 여우를 만난다.",
"options": {"threshold": 0.01}},
)
for match in resp.json()["matches"]:
assert match["match_reasons"], "채택 이유가 비어 있으면 안 된다"
assert set(match["match_reasons"]) <= {"score_threshold", "exact_span", "coverage"}