guvi-document-api / tests /test_api.py
shruthivihub
Initial commit: Intelligent Document Processing API
de76d9d
Raw History Blame Contribute Delete
9.08 kB
"""
Test Suite for Document Processing Pipeline
Tests each module independently and the full pipeline.
"""
import io
import sys
import os
import pytest
# Ensure the project root is in path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
# ── Text Cleaner Tests ─────────────────────────────────────────────────────────
class TestTextCleaner:
def setup_method(self):
from app.modules.text_cleaner import TextCleaner
self.cleaner = TextCleaner()
def test_basic_cleaning(self):
text = "Hello World\n\n\n\nThis is a test."
result = self.cleaner.clean(text)
assert "Hello World" in result
assert "\n\n\n" not in result
def test_ligature_replacement(self):
text = "\ufb01le \ufb02ow" # fi fl ligatures
result = self.cleaner.clean(text)
assert "file flow" in result
def test_noise_removal(self):
text = "Important text\n1\n---\nMore text"
result = self.cleaner.clean(text)
assert "Important text" in result
assert "More text" in result
def test_empty_input(self):
assert self.cleaner.clean("") == ""
assert self.cleaner.clean(" ") == ""
# ── Entity Extractor Tests ─────────────────────────────────────────────────────
class TestEntityExtractor:
def setup_method(self):
from app.modules.entity_extractor import EntityExtractor
self.extractor = EntityExtractor()
def test_extract_persons(self):
text = "John Smith and Jane Doe signed the agreement."
result = self.extractor.extract(text)
assert "persons" in result
# At least one person should be found
persons_lower = [p.lower() for p in result["persons"]]
assert any("john" in p or "jane" in p for p in persons_lower)
def test_extract_organizations(self):
text = "Google LLC and Microsoft Corporation announced a partnership."
result = self.extractor.extract(text)
orgs_lower = [o.lower() for o in result["organizations"]]
assert any("google" in o or "microsoft" in o for o in orgs_lower)
def test_extract_money(self):
text = "The deal was worth $5 million."
result = self.extractor.extract(text)
assert len(result["amounts"]) > 0
assert any("5" in a for a in result["amounts"])
def test_extract_dates(self):
text = "The contract was signed on January 15, 2024."
result = self.extractor.extract(text)
assert len(result["dates"]) > 0
def test_extract_locations(self):
text = "The company is headquartered in New York."
result = self.extractor.extract(text)
locs_lower = [l.lower() for l in result["locations"]]
assert any("new york" in l for l in locs_lower)
def test_empty_text(self):
result = self.extractor.extract("")
assert result["persons"] == []
assert result["organizations"] == []
def test_result_structure(self):
result = self.extractor.extract("Test text")
assert "persons" in result
assert "organizations" in result
assert "dates" in result
assert "amounts" in result
assert "locations" in result
# ── Sentiment Analyzer Tests ────────────────────────────────────────────────────
class TestSentimentAnalyzer:
def setup_method(self):
from app.modules.sentiment_analyzer import SentimentAnalyzer
self.analyzer = SentimentAnalyzer()
def test_positive_sentiment(self):
text = "This is an excellent product! We are very happy with the outstanding results and remarkable performance."
result = self.analyzer.analyze(text)
assert result in ("positive", "negative", "neutral") # Must be valid
def test_negative_sentiment(self):
text = "This is a terrible disaster. The project completely failed and caused enormous losses."
result = self.analyzer.analyze(text)
assert result in ("positive", "negative", "neutral")
def test_neutral_sentiment(self):
text = "The report was submitted on Monday. It includes figures from Q3 2024."
result = self.analyzer.analyze(text)
assert result in ("positive", "negative", "neutral")
def test_empty_text(self):
result = self.analyzer.analyze("")
assert result == "neutral"
def test_short_text(self):
result = self.analyzer.analyze("ok")
assert result == "neutral"
# ── Summarizer Tests ────────────────────────────────────────────────────────────
class TestSummarizer:
def setup_method(self):
from app.modules.summarizer import Summarizer
self.summarizer = Summarizer()
def test_summarize_returns_string(self):
text = (
"Artificial intelligence is transforming industries worldwide. "
"Companies are investing billions in AI research and development. "
"Machine learning models are being applied to healthcare, finance, and education. "
"The technology promises to automate complex tasks and improve decision making. "
"However, concerns about job displacement and ethical AI remain significant challenges."
)
result = self.summarizer.summarize(text)
assert isinstance(result, str)
assert len(result) > 0
def test_short_text_passthrough(self):
text = "Short text."
result = self.summarizer.summarize(text)
assert isinstance(result, str)
def test_empty_text(self):
result = self.summarizer.summarize("")
assert result == ""
# ── OCR Processor Tests ─────────────────────────────────────────────────────────
class TestOCRProcessor:
def setup_method(self):
from app.modules.ocr_processor import OCRProcessor
self.ocr = OCRProcessor()
def test_preprocess_returns_array(self):
from PIL import Image
import numpy as np
img = Image.new("RGB", (100, 100), color="white")
result = self.ocr.preprocess(img)
assert isinstance(result, np.ndarray)
def test_clean_ocr_output(self):
raw = "Hello World\n\n\n\ntest"
result = self.ocr._clean_ocr_output(raw)
assert "Hello World" in result
# ── API Integration Test ─────────────────────────────────────────────────────────
class TestAPIEndpoint:
def test_health_check(self):
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "healthy"
def test_analyze_empty_file(self):
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
response = client.post(
"/analyze",
files={"file": ("test.txt", b"", "text/plain")},
)
assert response.status_code in (400, 422)
def test_analyze_text_as_pdf_structure(self):
"""Test that the API returns the correct response structure."""
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
# Create a minimal valid DOCX in memory
from docx import Document
doc = Document()
doc.add_paragraph(
"Google and Microsoft announced a $10 million partnership in New York on January 15, 2024. "
"CEO John Smith stated the collaboration would bring excellent results for both companies."
)
buf = io.BytesIO()
doc.save(buf)
buf.seek(0)
response = client.post(
"/analyze",
files={"file": ("test.docx", buf.read(), "application/vnd.openxmlformats-officedocument.wordprocessingml.document")},
)
assert response.status_code == 200
data = response.json()
assert "summary" in data
assert "entities" in data
assert "sentiment" in data
assert "persons" in data["entities"]
assert "organizations" in data["entities"]
assert "dates" in data["entities"]
assert "amounts" in data["entities"]
assert "locations" in data["entities"]
assert data["sentiment"] in ("positive", "negative", "neutral")
if __name__ == "__main__":
pytest.main([__file__, "-v", "--tb=short"])