Spaces:
Running
Running
import pytest | |
from unittest.mock import patch, MagicMock | |
from io import BytesIO | |
# Import all functions to test | |
from utils import ( | |
extract_keywords, | |
parse_resume, | |
extract_email, | |
score_candidate, | |
summarize_resume, | |
filter_resumes_by_keywords, | |
evaluate_resumes, | |
store_in_supabase, | |
generate_pdf_report, | |
generate_interview_questions_from_summaries | |
) | |
# Run Command for Full Coverage Report: pytest --cov=utils --cov-report=term-missing -v | |
# --- Mock Models and External APIs --- | |
def patch_embedding_model(monkeypatch): | |
mock_model = MagicMock() | |
mock_model.encode.return_value = [0.1, 0.2, 0.3] | |
monkeypatch.setattr("utils.embedding_model", mock_model) | |
def patch_spacy(monkeypatch): | |
nlp_mock = MagicMock() | |
nlp_mock.return_value = [MagicMock(text="python", pos_="NOUN", is_stop=False)] | |
monkeypatch.setattr("utils.nlp", nlp_mock) | |
# --- extract_keywords --- | |
def test_extract_keywords(): | |
text = "We are looking for a Python developer with Django and REST experience." | |
keywords = extract_keywords(text) | |
assert isinstance(keywords, list) | |
assert "python" in keywords or len(keywords) > 0 | |
# --- parse_resume --- | |
def test_parse_resume(): | |
dummy_pdf = MagicMock() | |
dummy_pdf.read.return_value = b"%PDF-1.4" | |
with patch("fitz.open") as mocked_fitz: | |
page_mock = MagicMock() | |
page_mock.get_text.return_value = "Resume Text Here" | |
mocked_fitz.return_value = [page_mock] | |
result = parse_resume(dummy_pdf) | |
assert "Resume Text" in result | |
# --- extract_email --- | |
def test_extract_email(): | |
text = "Contact me at johndoe@example.com for more info." | |
assert extract_email(text) == "johndoe@example.com" | |
assert extract_email("No email here!") is None | |
# --- score_candidate --- | |
def test_score_candidate(): | |
score = score_candidate("Experienced Python developer", "Looking for Python engineer") | |
assert isinstance(score, float) | |
assert 0 <= score <= 1 | |
# --- summarize_resume --- | |
def test_summarize_resume(mock_query): | |
mock_query.return_value = [{"generated_text": "This is a summary"}] | |
summary = summarize_resume("This is a long resume text.") | |
assert summary == "This is a summary" | |
mock_query.return_value = None | |
fallback = summarize_resume("Another resume") | |
assert "unavailable" in fallback.lower() | |
# --- filter_resumes_by_keywords --- | |
def test_filter_resumes_by_keywords(): | |
resumes = [ | |
{"name": "John", "resume": "python django rest api"}, | |
{"name": "Doe", "resume": "java spring"} | |
] | |
job_description = "Looking for a python developer with API knowledge." | |
filtered, removed = filter_resumes_by_keywords(resumes, job_description, min_keyword_match=1) | |
assert isinstance(filtered, list) | |
assert isinstance(removed, list) | |
assert len(filtered) + len(removed) == 2 | |
# --- evaluate_resumes --- | |
def test_evaluate_resumes(_, __, ___, ____): | |
class DummyFile: | |
def __init__(self, name): self.name = name | |
def read(self): return b"%PDF-1.4" | |
uploaded_files = [DummyFile("resume1.pdf")] | |
job_desc = "Looking for a python developer." | |
shortlisted, removed = evaluate_resumes(uploaded_files, job_desc) | |
assert len(shortlisted) == 1 | |
assert isinstance(removed, list) | |
# --- store_in_supabase --- | |
def test_store_in_supabase(mock_supabase): | |
table_mock = MagicMock() | |
table_mock.insert.return_value.execute.return_value = {"status": "success"} | |
mock_supabase.table.return_value = table_mock | |
response = store_in_supabase("text", 0.8, "John", "john@example.com", "summary") | |
assert "status" in response | |
# --- generate_pdf_report --- | |
def test_generate_pdf_report(): | |
candidates = [{ | |
"name": "John Doe", | |
"email": "john@example.com", | |
"score": 0.87, | |
"summary": "Python developer" | |
}] | |
pdf = generate_pdf_report(candidates, questions=["What are your strengths?"]) | |
assert isinstance(pdf, BytesIO) | |
# --- generate_interview_questions_from_summaries --- | |
def test_generate_interview_questions_from_summaries(mock_chat): | |
mock_chat.return_value.choices = [ | |
MagicMock(message=MagicMock(content=""" | |
1. What are your strengths? | |
2. Describe a project you've led. | |
3. How do you handle tight deadlines? | |
""")) | |
] | |
candidates = [{"summary": "Experienced Python developer"}] | |
questions = generate_interview_questions_from_summaries(candidates) | |
assert len(questions) > 0 | |
assert all(q.startswith("Q") for q in questions) | |
def test_store_in_supabase(mock_supabase): | |
mock_table = MagicMock() | |
mock_execute = MagicMock() | |
mock_execute.return_value = {"status": "success"} | |
# Attach mocks | |
mock_table.insert.return_value.execute = mock_execute | |
mock_supabase.table.return_value = mock_table | |
data = { | |
"resume_text": "Some text", | |
"score": 0.85, | |
"candidate_name": "Alice", | |
"email": "alice@example.com", | |
"summary": "Experienced backend developer" | |
} | |
response = store_in_supabase(**data) | |
assert response["status"] == "success" | |
mock_supabase.table.assert_called_once_with("candidates") | |
mock_table.insert.assert_called_once() | |
inserted_data = mock_table.insert.call_args[0][0] | |
assert inserted_data["name"] == "Alice" | |
assert inserted_data["email"] == "alice@example.com" | |
def test_extract_keywords_empty_input(): | |
assert extract_keywords("") == [] | |
def test_extract_email_malformed(): | |
malformed_text = "email at example dot com" | |
assert extract_email(malformed_text) is None | |
def test_score_candidate_failure(monkeypatch): | |
def broken_encode(*args, **kwargs): raise Exception("fail") | |
monkeypatch.setattr("utils.embedding_model.encode", broken_encode) | |
score = score_candidate("resume", "job description") | |
assert score == 0 | |
def test_summarize_resume_bad_response(mock_query): | |
mock_query.return_value = {"weird_key": "no summary here"} | |
summary = summarize_resume("Resume text") | |
assert "unavailable" in summary.lower() | |
def test_summarize_resume_bad_response(mock_query): | |
mock_query.return_value = {"weird_key": "no summary here"} | |
summary = summarize_resume("Resume text") | |
assert "unavailable" in summary.lower() | |
def test_evaluate_resumes_low_score_filtered(_, __, ___, ____): | |
class Dummy: | |
name = "resume.pdf" | |
def read(self): return b"%PDF" | |
uploaded = [Dummy()] | |
shortlisted, removed = evaluate_resumes(uploaded, "job description") | |
assert len(shortlisted) == 0 | |
assert len(removed) == 1 |