Spaces:
Configuration error
Configuration error
""" | |
Unit tests for the gradio module. | |
""" | |
import unittest | |
from pathlib import Path | |
from unittest.mock import patch | |
from functions import gradio | |
class TestProcessInputs(unittest.TestCase): | |
"""Test cases for the process_inputs function.""" | |
def test_process_inputs_with_real_pdf(self): | |
"""Test process_inputs with the actual test PDF file.""" | |
# Get path to the test PDF file | |
test_pdf_path = Path(__file__).parent / "test_data" / "linkedin_profile.pdf" | |
# Skip test if PDF doesn't exist (optional test data) | |
if not test_pdf_path.exists(): | |
self.skipTest(f"Test PDF file not found: {test_pdf_path}") | |
with patch('functions.gradio.extract_text') as mock_extract, \ | |
patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.summarize_job_call') as mock_job_call, \ | |
patch('functions.gradio.write_resume') as mock_write_resume: | |
mock_extract.return_value = {"test": "data"} | |
mock_github.return_value = [{"name": "test-repo"}] | |
mock_job_call.return_value = {"title": "Software Engineer", "requirements": ["Python"]} | |
mock_write_resume.return_value = "# Generated Resume\n\nTest resume content" | |
result = gradio.process_inputs( | |
linkedin_pdf_path=str(test_pdf_path), | |
github_username="testuser", | |
job_post_text="Software engineer position" | |
) | |
# Verify all functions were called | |
mock_extract.assert_called_once_with(str(test_pdf_path)) | |
mock_github.assert_called_once_with("testuser") | |
mock_job_call.assert_called_once_with("Software engineer position") | |
mock_write_resume.assert_called_once_with( | |
{"test": "data"}, | |
[{"name": "test-repo"}], | |
{"title": "Software Engineer", "requirements": ["Python"]} | |
) | |
# Function should return the generated resume | |
self.assertEqual(result, "# Generated Resume\n\nTest resume content") | |
def test_process_inputs_with_pdf_path_mocked( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test process_inputs with a PDF file path (mocked for controlled testing).""" | |
# Mock successful LinkedIn text extraction | |
mock_extract.return_value = { | |
"contact_info": "John Doe, email@example.com", | |
"summary": "Experienced software engineer", | |
"experience": "Software Engineer at Company" | |
} | |
mock_github.return_value = [{"name": "test-repo"}] | |
mock_job_call.return_value = { | |
"title": "Software Engineer", | |
"requirements": ["Python", "JavaScript"] | |
} | |
mock_write_resume.return_value = "# John Doe\n\n## Summary\nExperienced software engineer" | |
result = gradio.process_inputs( | |
linkedin_pdf_path="/path/to/resume.pdf", | |
github_username="testuser", | |
job_post_text="Software engineer position" | |
) | |
# Verify extract_text was called with the correct path | |
mock_extract.assert_called_once_with("/path/to/resume.pdf") | |
# Verify get_github_repositories was called with username | |
mock_github.assert_called_once_with("testuser") | |
# Verify job post was processed | |
mock_job_call.assert_called_once_with("Software engineer position") | |
# Verify resume generation was called with correct arguments | |
mock_write_resume.assert_called_once() | |
# Function should return the generated resume content | |
self.assertEqual(result, "# John Doe\n\n## Summary\nExperienced software engineer") | |
def test_process_inputs_extraction_failure( | |
self, mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test process_inputs when LinkedIn extraction fails.""" | |
# Mock failed LinkedIn text extraction | |
mock_extract.return_value = None | |
mock_github.return_value = None | |
mock_job_call.return_value = None | |
result = gradio.process_inputs( | |
linkedin_pdf_path="/path/to/resume.pdf", | |
github_username="testuser", | |
job_post_text="Software engineer position" | |
) | |
# Verify extract_text was called | |
mock_extract.assert_called_once_with("/path/to/resume.pdf") | |
mock_github.assert_called_once_with("testuser") | |
mock_job_call.assert_called_once_with("Software engineer position") | |
# write_resume should NOT be called when data is missing | |
mock_write_resume.assert_not_called() | |
# Function should return empty string when processing fails | |
self.assertEqual(result, "") | |
def test_process_inputs_no_pdf_path( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test process_inputs with no PDF path provided.""" | |
mock_extract.return_value = None | |
mock_github.return_value = [] | |
mock_job_call.return_value = {"title": "Software Engineer"} | |
result = gradio.process_inputs( | |
linkedin_pdf_path=None, | |
github_username="testuser", | |
job_post_text="Software engineer position" | |
) | |
# extract_text should be called with None | |
mock_extract.assert_called_once_with(None) | |
mock_github.assert_called_once_with("testuser") | |
mock_job_call.assert_called_once_with("Software engineer position") | |
# write_resume should NOT be called when LinkedIn data is missing | |
mock_write_resume.assert_not_called() | |
# Function should return empty string when data is insufficient | |
self.assertEqual(result, "") | |
def test_process_inputs_with_long_job_post( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test process_inputs with a long job post text (for logging truncation).""" | |
mock_extract.return_value = { | |
"summary": "Test summary" | |
} | |
mock_github.return_value = [] | |
mock_job_call.return_value = {"title": "Software Engineer", "requirements": ["Python"]} | |
long_job_post = "This is a very long job posting " * 50 # Make it longer than 100 chars | |
result = gradio.process_inputs( | |
linkedin_pdf_path="/path/to/resume.pdf", | |
github_username="testuser", | |
job_post_text=long_job_post | |
) | |
# Verify extract_text was called | |
mock_extract.assert_called_once_with("/path/to/resume.pdf") | |
mock_github.assert_called_once_with("testuser") | |
mock_job_call.assert_called_once_with(long_job_post.strip()) | |
# write_resume should NOT be called when GitHub repos are empty | |
mock_write_resume.assert_not_called() | |
# Function should return empty string when GitHub data is missing | |
self.assertEqual(result, "") | |
def test_process_inputs_github_username_whitespace( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test that github_username is properly stripped of whitespace.""" | |
mock_extract.return_value = None | |
mock_github.return_value = [] | |
mock_job_call.return_value = {"title": "Engineer"} | |
result = gradio.process_inputs( | |
linkedin_pdf_path=None, | |
github_username=" testuser ", | |
job_post_text="" | |
) | |
# Verify get_github_repositories was called with stripped username | |
mock_github.assert_called_once_with("testuser") | |
mock_write_resume.assert_not_called() | |
self.assertEqual(result, "") | |
def test_logging_calls( | |
self, | |
mock_get_logger, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test that appropriate logging calls are made.""" | |
mock_logger = mock_get_logger.return_value | |
mock_extract.return_value = {"test": "data"} | |
mock_github.return_value = [{"name": "repo"}] | |
mock_job_call.return_value = {"title": "Engineer"} | |
mock_write_resume.return_value = "# Resume Content" | |
result = gradio.process_inputs( | |
linkedin_pdf_path="/path/to/resume.pdf", | |
github_username="testuser", | |
job_post_text="Job description here" | |
) | |
# Verify logging calls were made | |
mock_logger.info.assert_called() | |
# Verify resume was generated successfully | |
self.assertEqual(result, "# Resume Content") | |
def test_process_inputs_write_resume_exception( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test process_inputs when write_resume raises an exception.""" | |
mock_extract.return_value = {"test": "data"} | |
mock_github.return_value = [{"name": "repo"}] | |
mock_job_call.return_value = {"title": "Engineer"} | |
mock_write_resume.side_effect = Exception("API Error") | |
result = gradio.process_inputs( | |
linkedin_pdf_path="/path/to/resume.pdf", | |
github_username="testuser", | |
job_post_text="Job description here" | |
) | |
# Verify all functions were called | |
mock_extract.assert_called_once_with("/path/to/resume.pdf") | |
mock_github.assert_called_once_with("testuser") | |
mock_job_call.assert_called_once_with("Job description here") | |
mock_write_resume.assert_called_once() | |
# Function should return empty string when write_resume fails | |
self.assertEqual(result, "") | |
def test_process_inputs_complete_success_flow( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test the complete successful flow with all components working.""" | |
# Mock all successful responses | |
linkedin_data = { | |
"contact_info": "Jane Doe, jane@example.com", | |
"summary": "Senior Python Developer", | |
"experience": "5 years experience in Python development" | |
} | |
github_repos = [ | |
{"name": "awesome-python-app", "description": "A Python web application"}, | |
{"name": "data-analysis-tool", "description": "Data analysis with pandas"} | |
] | |
job_data = { | |
"title": "Senior Python Developer", | |
"requirements": ["Python", "Django", "PostgreSQL"], | |
"company": "Tech Corp" | |
} | |
resume_content = ( | |
"# Jane Doe\n\n## Experience\n" | |
"Senior Python Developer with 5 years experience..." | |
) | |
mock_extract.return_value = linkedin_data | |
mock_github.return_value = github_repos | |
mock_job_call.return_value = job_data | |
mock_write_resume.return_value = resume_content | |
result = gradio.process_inputs( | |
linkedin_pdf_path="/path/to/jane_resume.pdf", | |
github_username="jane_dev", | |
job_post_text="We are looking for a Senior Python Developer with Django experience..." | |
) | |
# Verify all functions were called with correct arguments | |
mock_extract.assert_called_once_with("/path/to/jane_resume.pdf") | |
mock_github.assert_called_once_with("jane_dev") | |
mock_job_call.assert_called_once_with( | |
"We are looking for a Senior Python Developer with Django experience..." | |
) | |
mock_write_resume.assert_called_once_with(linkedin_data, github_repos, job_data) | |
# Verify the complete resume is returned | |
self.assertEqual(result, resume_content) | |
self.assertIn("Jane Doe", result) | |
self.assertIn("Senior Python Developer", result) | |
def test_process_inputs_none_github_username( | |
self, | |
mock_github, | |
mock_extract, | |
mock_job_call, | |
mock_write_resume | |
): | |
"""Test process_inputs with None github_username (should handle gracefully).""" | |
mock_extract.return_value = None | |
mock_github.return_value = None | |
mock_job_call.return_value = None | |
# This should raise a TypeError due to the bug in gradio.py | |
# where it tries to slice job_post_text[:100] when job_post_text is None | |
with self.assertRaises(TypeError): | |
gradio.process_inputs( | |
linkedin_pdf_path=None, | |
github_username=None, | |
job_post_text=None | |
) | |
if __name__ == '__main__': | |
unittest.main() | |