Spaces:
Configuration error
Configuration error
""" | |
Unit tests for the gradio module. | |
""" | |
import unittest | |
from unittest.mock import patch, MagicMock | |
from functions import gradio | |
class TestProcessInputs(unittest.TestCase): | |
"""Test cases for the process_inputs function.""" | |
def test_no_inputs_provided(self, mock_load_default): | |
"""Test when no inputs are provided and default job is available.""" | |
# Mock default job call loading to return content | |
mock_load_default.return_value = "Default job content from sample_job.txt" | |
with patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.summarize_job_call') as mock_summarize: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
mock_summarize.return_value = "Mocked job summary" | |
result = gradio.process_inputs(None, "", "", "") | |
self.assertIn("β No LinkedIn resume PDF file uploaded", result) | |
self.assertIn("β Using default GitHub Profile URL", result) | |
self.assertIn("βΉοΈ No job post provided, attempting to use default", result) | |
self.assertIn("β Using default job post", result) | |
self.assertIn("βΉοΈ No additional instructions provided", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
def test_no_inputs_no_default_job(self, mock_load_default): | |
"""Test when no inputs are provided and no default job is available.""" | |
# Mock default job call loading to return None (no default available) | |
mock_load_default.return_value = None | |
with patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.summarize_job_call') as mock_summarize: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
mock_summarize.return_value = None # No summarization since no job post | |
result = gradio.process_inputs(None, "", "", "") | |
self.assertIn("β No LinkedIn resume PDF file uploaded", result) | |
self.assertIn("β Using default GitHub Profile URL", result) | |
self.assertIn("βΉοΈ No job post provided, attempting to use default", result) | |
self.assertIn("βΉοΈ No default job post available, proceeding without job post", result) | |
self.assertIn("βΉοΈ Proceeding without job post analysis", result) | |
self.assertIn("βΉοΈ No additional instructions provided", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
def test_all_inputs_provided_success(self): | |
"""Test when all inputs are provided and successful.""" | |
# Mock LinkedIn PDF file | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test_resume.pdf" | |
# Mock successful extraction results | |
mock_linkedin_result = { | |
"status": "success", | |
"structured_text": {"sections": {}, "llm_formatted": "test content"}, | |
"metadata": {"filename": "test_resume.pdf"} | |
} | |
mock_github_result = { | |
"status": "success", | |
"repositories": [{"name": "test-repo"}], | |
"metadata": {"username": "testuser"} | |
} | |
with patch('functions.gradio.extract_text_from_linkedin_pdf') as mock_linkedin, \ | |
patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.write_resume') as mock_write_resume, \ | |
patch('functions.gradio.summarize_job_call') as mock_summarize: #, \ | |
#patch('functions.gradio.shutil.copy2') as mock_copy: | |
mock_linkedin.return_value = mock_linkedin_result | |
mock_github.return_value = mock_github_result | |
mock_write_resume.return_value = "Generated resume content" | |
mock_summarize.return_value = "Job summary content\n" | |
result = gradio.process_inputs( | |
mock_pdf, | |
"https://github.com/testuser", | |
"Job posting text here", | |
"Please emphasize technical skills" | |
) | |
self.assertIn("β LinkedIn Resume PDF provided", result) | |
self.assertIn("β Text extraction successful", result) | |
self.assertIn("β GitHub Profile URL provided", result) | |
self.assertIn("β GitHub list download successful", result) | |
self.assertIn("β Job post text provided", result) | |
self.assertIn("β Job post summary generated", result) | |
self.assertIn("β Additional instructions provided", result) | |
self.assertIn("β Resume generated successfully", result) | |
# Verify write_resume was called with user instructions and job summary | |
mock_write_resume.assert_called_with( | |
mock_linkedin_result, | |
"Please emphasize technical skills", | |
"Job summary content\n" | |
) | |
def test_linkedin_extraction_failure(self, mock_write_resume, mock_extract): | |
"""Test LinkedIn PDF extraction failure.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test_resume.pdf" | |
mock_extract.return_value = { | |
"status": "error", | |
"message": "Failed to read PDF" | |
} | |
mock_write_resume.return_value = "Generated resume content" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
result = gradio.process_inputs(mock_pdf, "", "", "") | |
self.assertIn("β LinkedIn Resume PDF provided", result) | |
self.assertIn("β Text extraction failed: Failed to read PDF", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
# Verify write_resume was NOT called since extraction failed | |
mock_write_resume.assert_not_called() | |
def test_linkedin_extraction_warning(self, mock_write_resume, mock_extract): | |
"""Test LinkedIn PDF extraction warning.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test_resume.pdf" | |
mock_extract.return_value = { | |
"status": "warning", | |
"message": "No text found in PDF" | |
} | |
mock_write_resume.return_value = "Generated resume content" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
result = gradio.process_inputs(mock_pdf, "", "", "") | |
self.assertIn("β LinkedIn Resume PDF provided", result) | |
self.assertIn("β οΈ Text extraction: No text found in PDF", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
# Verify write_resume was NOT called since extraction had warning status | |
mock_write_resume.assert_not_called() | |
def test_github_retrieval_failure(self, mock_write_resume, mock_github): | |
"""Test GitHub repository retrieval failure.""" | |
mock_github.return_value = { | |
"status": "error", | |
"message": "User not found" | |
} | |
mock_write_resume.return_value = "Generated resume content" | |
result = gradio.process_inputs(None, "https://github.com/nonexistent", "", "") | |
self.assertIn("β GitHub Profile URL provided", result) | |
self.assertIn("β GitHub extraction failed: User not found", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
# Verify write_resume was NOT called since no LinkedIn data | |
mock_write_resume.assert_not_called() | |
def test_whitespace_only_inputs(self, mock_load_default): | |
"""Test inputs with only whitespace and default job available.""" | |
# Mock default job call loading to return content | |
mock_load_default.return_value = "Default job content from sample_job.txt" | |
with patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.summarize_job_call') as mock_summarize: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
mock_summarize.return_value = "Mocked job summary" | |
result = gradio.process_inputs(None, " ", " ", " ") | |
self.assertIn("β No LinkedIn resume PDF file uploaded", result) | |
self.assertIn("β Using default GitHub Profile URL", result) | |
self.assertIn("βΉοΈ No job post provided, attempting to use default", result) | |
self.assertIn("β Using default job post", result) | |
self.assertIn("βΉοΈ No additional instructions provided", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
def test_whitespace_only_inputs_no_default(self, mock_load_default): | |
"""Test inputs with only whitespace and no default job available.""" | |
# Mock default job call loading to return None | |
mock_load_default.return_value = None | |
with patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.summarize_job_call') as mock_summarize: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
mock_summarize.return_value = None # No summarization since no job post | |
result = gradio.process_inputs(None, " ", " ", " ") | |
self.assertIn("β No LinkedIn resume PDF file uploaded", result) | |
self.assertIn("β Using default GitHub Profile URL", result) | |
self.assertIn("βΉοΈ No job post provided, attempting to use default", result) | |
self.assertIn("βΉοΈ No default job post available, proceeding without job post", result) | |
self.assertIn("βΉοΈ Proceeding without job post analysis", result) | |
self.assertIn("βΉοΈ No additional instructions provided", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
def test_job_post_with_content(self, mock_summarize, mock_write_resume): | |
"""Test job post with actual content.""" | |
job_text = "Software Engineer position at Tech Company" | |
mock_write_resume.return_value = "Generated resume content" | |
mock_summarize.return_value = "Job summary content\n" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
result = gradio.process_inputs(None, "", job_text, "") | |
self.assertIn("β Job post text provided", result) | |
self.assertIn("β Job post summary generated", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
# Verify write_resume was NOT called since no LinkedIn data | |
mock_write_resume.assert_not_called() | |
def test_logging_calls(self, mock_write_resume, mock_logger): | |
"""Test that appropriate logging calls are made.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test.pdf" | |
mock_write_resume.return_value = "Generated resume content" | |
with patch('functions.gradio.extract_text_from_linkedin_pdf') as mock_extract, \ | |
patch('functions.gradio.get_github_repositories') as mock_github, \ | |
patch('functions.gradio.summarize_job_call') as mock_summarize: | |
mock_extract.return_value = {"status": "success"} | |
mock_github.return_value = {"status": "success", "metadata": {"username": "test"}} | |
mock_summarize.return_value = "Job summary\n" | |
gradio.process_inputs( | |
mock_pdf, | |
"https://github.com/test", | |
"job text", | |
"custom instructions" | |
) | |
# Verify logging calls were made | |
mock_logger.info.assert_called() | |
def test_user_instructions_with_content(self, mock_write_resume): | |
"""Test user instructions with actual content.""" | |
instructions = "Please emphasize leadership skills and highlight remote work experience" | |
mock_write_resume.return_value = "Generated resume content" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
result = gradio.process_inputs(None, "", "", instructions) | |
self.assertIn("β Additional instructions provided", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
# Verify write_resume was NOT called since no valid extraction result | |
mock_write_resume.assert_not_called() | |
def test_user_instructions_empty(self, mock_write_resume): | |
"""Test user instructions when empty.""" | |
mock_write_resume.return_value = "Generated resume content" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = {"status": "success", "metadata": {"username": "gperdrizet"}} | |
result = gradio.process_inputs(None, "", "", "") | |
self.assertIn("βΉοΈ No additional instructions provided", result) | |
self.assertIn("β Cannot generate resume: No valid LinkedIn data extracted", result) | |
# Verify write_resume was NOT called since no valid extraction result | |
mock_write_resume.assert_not_called() | |
class TestGetProcessedData(unittest.TestCase): | |
"""Test cases for the get_processed_data function.""" | |
def test_no_inputs(self, mock_load_default): | |
"""Test with no inputs provided.""" | |
# Mock the default job call loading | |
mock_load_default.return_value = "Default job call content from sample_job.txt" | |
result = gradio.get_processed_data(None, "", "", "") | |
self.assertIsNone(result["linkedin"]) | |
self.assertIsNone(result["github"]) | |
self.assertEqual(result["job_post"], "Default job call content from sample_job.txt") | |
self.assertIsNone(result["user_instructions"]) | |
self.assertEqual(len(result["errors"]), 0) | |
def test_no_inputs_no_default_job(self, mock_load_default): | |
"""Test with no inputs provided and no default job available.""" | |
# Mock the default job call loading to return None | |
mock_load_default.return_value = None | |
result = gradio.get_processed_data(None, "", "", "") | |
self.assertIsNone(result["linkedin"]) | |
self.assertIsNone(result["github"]) | |
self.assertIsNone(result["job_post"]) | |
self.assertIsNone(result["user_instructions"]) | |
self.assertEqual(len(result["errors"]), 0) | |
def test_all_successful_inputs(self): | |
"""Test with all successful inputs.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test.pdf" | |
mock_linkedin_result = { | |
"status": "success", | |
"structured_text": {"sections": {}, "llm_formatted": "content"} | |
} | |
mock_github_result = { | |
"status": "success", | |
"repositories": [{"name": "repo"}], | |
"metadata": {"username": "user"} | |
} | |
with patch('functions.gradio.extract_text_from_linkedin_pdf') as mock_linkedin, \ | |
patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_linkedin.return_value = mock_linkedin_result | |
mock_github.return_value = mock_github_result | |
result = gradio.get_processed_data( | |
mock_pdf, | |
"https://github.com/user", | |
"Job posting content", | |
"Custom instructions" | |
) | |
self.assertEqual(result["linkedin"], mock_linkedin_result) | |
self.assertEqual(result["github"], mock_github_result) | |
self.assertEqual(result["job_post"], "Job posting content") | |
self.assertEqual(result["user_instructions"], "Custom instructions") | |
self.assertEqual(len(result["errors"]), 0) | |
def test_linkedin_error(self): | |
"""Test with LinkedIn processing error.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test.pdf" | |
with patch('functions.gradio.extract_text_from_linkedin_pdf') as mock_extract: | |
mock_extract.return_value = { | |
"status": "error", | |
"message": "PDF read failed" | |
} | |
result = gradio.get_processed_data(mock_pdf, "", "", "") | |
self.assertIsNone(result["linkedin"]) | |
self.assertEqual(len(result["errors"]), 1) | |
self.assertIn("LinkedIn: PDF read failed", result["errors"]) | |
def test_github_error(self): | |
"""Test with GitHub processing error.""" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = { | |
"status": "error", | |
"message": "User not found" | |
} | |
result = gradio.get_processed_data(None, "https://github.com/invalid", "", "") | |
self.assertIsNone(result["github"]) | |
self.assertEqual(len(result["errors"]), 1) | |
self.assertIn("GitHub: User not found", result["errors"]) | |
def test_multiple_errors(self): | |
"""Test with multiple processing errors.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test.pdf" | |
with patch('functions.gradio.extract_text_from_linkedin_pdf') as mock_linkedin, \ | |
patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_linkedin.return_value = { | |
"status": "error", | |
"message": "LinkedIn error" | |
} | |
mock_github.return_value = { | |
"status": "error", | |
"message": "GitHub error" | |
} | |
result = gradio.get_processed_data( | |
mock_pdf, | |
"https://github.com/user", | |
"", | |
"" | |
) | |
self.assertIsNone(result["linkedin"]) | |
self.assertIsNone(result["github"]) | |
self.assertEqual(len(result["errors"]), 2) | |
self.assertIn("LinkedIn: LinkedIn error", result["errors"]) | |
self.assertIn("GitHub: GitHub error", result["errors"]) | |
def test_job_post_whitespace_handling(self, mock_load_default): | |
"""Test job post whitespace handling.""" | |
# Mock the default job call loading | |
mock_load_default.return_value = "Default job content" | |
# Test with leading/trailing whitespace | |
result = gradio.get_processed_data(None, "", " Job content ", "") | |
self.assertEqual(result["job_post"], "Job content") | |
# Test with only whitespace - should load default | |
result = gradio.get_processed_data(None, "", " ", "") | |
self.assertEqual(result["job_post"], "Default job content") | |
# Test with empty string - should load default | |
result = gradio.get_processed_data(None, "", "", "") | |
self.assertEqual(result["job_post"], "Default job content") | |
def test_github_url_whitespace_handling(self): | |
"""Test GitHub URL whitespace handling.""" | |
with patch('functions.gradio.get_github_repositories') as mock_github: | |
mock_github.return_value = {"status": "success", "repositories": []} | |
# Test with leading/trailing whitespace | |
_ = gradio.get_processed_data(None, " https://github.com/user ", "", "") | |
mock_github.assert_called_with(" https://github.com/user ") | |
# Test with only whitespace - should not call function | |
mock_github.reset_mock() | |
_ = gradio.get_processed_data(None, " ", "", "") | |
mock_github.assert_not_called() | |
def test_data_structure_consistency(self): | |
"""Test that returned data structure is consistent.""" | |
result = gradio.get_processed_data(None, "", "", "") | |
# Check all required keys exist | |
required_keys = ["linkedin", "github", "job_post", "user_instructions", "errors"] | |
for key in required_keys: | |
self.assertIn(key, result) | |
# Check data types | |
self.assertIsInstance(result["errors"], list) | |
def test_linkedin_warning_status(self, mock_extract): | |
"""Test handling of LinkedIn warning status.""" | |
mock_pdf = MagicMock() | |
mock_pdf.name = "test.pdf" | |
mock_extract.return_value = { | |
"status": "warning", | |
"message": "Some warning" | |
} | |
result = gradio.get_processed_data(mock_pdf, "", "", "") | |
# Warning status should not be treated as success | |
self.assertIsNone(result["linkedin"]) | |
self.assertEqual(len(result["errors"]), 1) | |
self.assertIn("LinkedIn: Some warning", result["errors"]) | |
def test_user_instructions_whitespace_handling(self): | |
"""Test user instructions whitespace handling.""" | |
# Test with leading/trailing whitespace | |
result = gradio.get_processed_data(None, "", "", " Custom instructions ") | |
self.assertEqual(result["user_instructions"], "Custom instructions") | |
# Test with only whitespace | |
result = gradio.get_processed_data(None, "", "", " ") | |
self.assertIsNone(result["user_instructions"]) | |
# Test with empty string | |
result = gradio.get_processed_data(None, "", "", "") | |
self.assertIsNone(result["user_instructions"]) | |
if __name__ == '__main__': | |
unittest.main() | |