174 lines
6.3 KiB
Python
174 lines
6.3 KiB
Python
import os
|
|
import sys
|
|
import pytest
|
|
from unittest.mock import patch, MagicMock
|
|
import json
|
|
import logging
|
|
import argparse # Import argparse
|
|
from dotenv import load_dotenv
|
|
|
|
# Add the project root to the sys path to allow imports from the main package
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
|
|
from resume_analysis import (
|
|
call_openai_api,
|
|
insert_processing_data,
|
|
load_mockup_response,
|
|
main,
|
|
get_mongo_collection
|
|
)
|
|
|
|
# Load environment variables for testing
|
|
load_dotenv()
|
|
|
|
# Constants for Mocking
|
|
MOCKUP_FILE_PATH = os.path.join(os.path.dirname(__file__), 'mockup_response.json')
|
|
TEST_RESUME_PATH = os.path.join(os.path.dirname(__file__), 'test_resume.txt')
|
|
|
|
# Create a logger
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
# Create a handler and set the formatter
|
|
ch = logging.StreamHandler()
|
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
ch.setFormatter(formatter)
|
|
|
|
# Add the handler to the logger
|
|
logger.addHandler(ch)
|
|
|
|
# Mockup response data
|
|
MOCKUP_RESPONSE_DATA = {
|
|
"id": "chatcmpl-123",
|
|
"object": "chat.completion",
|
|
"created": 1677652288,
|
|
"model": "gpt-3.5-turbo-0301",
|
|
"usage": {
|
|
"prompt_tokens": 100,
|
|
"completion_tokens": 200,
|
|
"total_tokens": 300
|
|
},
|
|
"choices": [
|
|
{
|
|
"message": {
|
|
"role": "assistant",
|
|
"content": '{"openai_stats": {"prompt_tokens": 100, "completion_tokens": 200, "total_tokens": 300}}'
|
|
},
|
|
"finish_reason": "stop",
|
|
"index": 0
|
|
}
|
|
]
|
|
}
|
|
|
|
# Fixtures
|
|
@pytest.fixture
|
|
def mock_openai_response():
|
|
mock_response = MagicMock()
|
|
mock_response.id = "chatcmpl-123"
|
|
mock_response.object = "chat.completion"
|
|
mock_response.created = 1677652288
|
|
mock_response.model = "gpt-3.5-turbo-0301"
|
|
mock_response.usage = MagicMock(prompt_tokens=100, completion_tokens=200, total_tokens=300)
|
|
mock_response.choices = [MagicMock(message=MagicMock(role="assistant", content='{"openai_stats": {"prompt_tokens": 100, "completion_tokens": 200, "total_tokens": 300}}'), finish_reason="stop", index=0)]
|
|
return mock_response
|
|
|
|
@pytest.fixture
|
|
def test_resume_file():
|
|
# Create a dummy resume file for testing
|
|
with open(TEST_RESUME_PATH, 'w') as f:
|
|
f.write("This is a test resume.")
|
|
yield TEST_RESUME_PATH
|
|
os.remove(TEST_RESUME_PATH)
|
|
|
|
@pytest.fixture
|
|
def mock_mongo_collection():
|
|
# Mock MongoDB collection for testing
|
|
class MockMongoCollection:
|
|
def __init__(self):
|
|
self.inserted_data = None
|
|
|
|
def insert_one(self, data):
|
|
self.inserted_data = data
|
|
|
|
return MockMongoCollection()
|
|
|
|
# Unit Tests
|
|
def test_load_mockup_response():
|
|
# Create a mockup response file
|
|
with open(MOCKUP_FILE_PATH, 'w') as f:
|
|
json.dump(MOCKUP_RESPONSE_DATA, f)
|
|
|
|
response = load_mockup_response(MOCKUP_FILE_PATH)
|
|
assert response == MOCKUP_RESPONSE_DATA
|
|
os.remove(MOCKUP_FILE_PATH)
|
|
|
|
def test_load_mockup_response_file_not_found():
|
|
with pytest.raises(FileNotFoundError):
|
|
load_mockup_response("non_existent_file.json")
|
|
|
|
@patch("resume_analysis.openai.chat.completions.create")
|
|
def test_call_openai_api_success(mock_openai_chat_completions_create, mock_openai_response):
|
|
mock_openai_chat_completions_create.return_value = mock_openai_response
|
|
response = call_openai_api("test resume text", False)
|
|
assert response == mock_openai_response
|
|
|
|
@patch("resume_analysis.openai.chat.completions.create")
|
|
def test_call_openai_api_failure(mock_openai_chat_completions_create):
|
|
mock_openai_chat_completions_create.side_effect = Exception("API error")
|
|
response = call_openai_api("test resume text", False)
|
|
assert response is None
|
|
|
|
def test_call_openai_api_mockup_mode():
|
|
# Create a mockup response file
|
|
with open(MOCKUP_FILE_PATH, 'w') as f:
|
|
json.dump(MOCKUP_RESPONSE_DATA, f)
|
|
|
|
response = call_openai_api("test resume text", True)
|
|
assert response == MOCKUP_RESPONSE_DATA
|
|
os.remove(MOCKUP_FILE_PATH)
|
|
|
|
def test_insert_processing_data_success(mock_openai_response, mock_mongo_collection):
|
|
args = argparse.Namespace(file="test.pdf")
|
|
cost = insert_processing_data("test resume text", {}, mock_openai_response, args, "test_id", False, mock_mongo_collection)
|
|
assert mock_mongo_collection.inserted_data is not None
|
|
assert cost == 0
|
|
|
|
def test_insert_processing_data_mockup_mode(mock_mongo_collection):
|
|
args = argparse.Namespace(file="test.pdf")
|
|
cost = insert_processing_data("test resume text", {}, MOCKUP_RESPONSE_DATA, args, "test_id", True, mock_mongo_collection)
|
|
assert mock_mongo_collection.inserted_data is None
|
|
assert cost == 0
|
|
|
|
@patch("resume_analysis.get_mongo_collection")
|
|
def test_main_success(mock_get_mongo_collection, test_resume_file, mock_openai_response):
|
|
mock_get_mongo_collection.return_value.insert_one.return_value = None
|
|
with patch("resume_analysis.call_openai_api") as mock_call_openai_api:
|
|
mock_call_openai_api.return_value = mock_openai_response
|
|
with patch("resume_analysis.write_openai_response") as mock_write_openai_response:
|
|
sys.argv = ["resume_analysis.py", "-f", test_resume_file]
|
|
main()
|
|
assert mock_call_openai_api.called
|
|
assert mock_write_openai_response.called
|
|
|
|
@patch("resume_analysis.get_mongo_collection")
|
|
def test_main_mockup_mode(mock_get_mongo_collection, test_resume_file, mock_openai_response):
|
|
mock_get_mongo_collection.return_value.insert_one.return_value = None
|
|
with patch("resume_analysis.call_openai_api") as mock_call_openai_api:
|
|
mock_call_openai_api.return_value = mock_openai_response
|
|
with patch("resume_analysis.write_openai_response") as mock_write_openai_response:
|
|
sys.argv = ["resume_analysis.py", "-f", test_resume_file, "-m"]
|
|
main()
|
|
assert mock_call_openai_api.called
|
|
assert mock_write_openai_response.called
|
|
|
|
def test_main_file_not_found():
|
|
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
|
sys.argv = ["resume_analysis.py", "-f", "non_existent_file.pdf"]
|
|
main()
|
|
assert pytest_wrapped_e.type == SystemExit
|
|
assert pytest_wrapped_e.value.code == 1
|
|
|
|
def test_get_mongo_collection():
|
|
# Test that the function returns a valid MongoDB collection object
|
|
collection = get_mongo_collection()
|
|
assert collection is not None |