252 lines
7.9 KiB
Python
252 lines
7.9 KiB
Python
"""
|
|
Tests for sentiment analysis worker.
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, patch
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.workers.sentiment_worker import (
|
|
SentimentWorker,
|
|
create_sentiment_worker
|
|
)
|
|
|
|
|
|
class TestSentimentWorker:
|
|
"""Tests for SentimentWorker class."""
|
|
|
|
def test_initialization(self):
|
|
"""Test sentiment worker initialization."""
|
|
worker = SentimentWorker()
|
|
|
|
# No specific initialization required for sentiment worker
|
|
assert worker is not None
|
|
|
|
@patch('app.workers.sentiment_worker.process_tweet_batch')
|
|
@patch('app.workers.sentiment_worker.get_sentiment_by_entity')
|
|
def test_execute_sentiment_analysis_task_twitter(
|
|
self,
|
|
mock_get_sentiment,
|
|
mock_process_batch
|
|
):
|
|
"""Test executing a Twitter sentiment analysis task."""
|
|
# Create worker
|
|
worker = SentimentWorker()
|
|
|
|
# Mock database session
|
|
mock_db = Mock(spec=Session)
|
|
|
|
# Mock tweet query
|
|
mock_tweets = [Mock()] * 100
|
|
mock_db.query.return_value.filter.return_value.all.return_value = mock_tweets
|
|
|
|
# Mock existing sentiment (none exist)
|
|
mock_get_sentiment.return_value = None
|
|
|
|
# Mock batch processing
|
|
mock_process_batch.return_value = [Mock()] * 100
|
|
|
|
# Mock calculate metrics
|
|
with patch.object(
|
|
worker,
|
|
'_calculate_sentiment_metrics',
|
|
return_value={
|
|
'total_count': 100,
|
|
'positive_count': 60,
|
|
'negative_count': 20,
|
|
'neutral_count': 20,
|
|
'average_compound': 0.35
|
|
}
|
|
):
|
|
# Execute task
|
|
task = {
|
|
'match_id': 123,
|
|
'source': 'twitter',
|
|
'entity_ids': ['tweet1', 'tweet2']
|
|
}
|
|
|
|
result = worker.execute_sentiment_analysis_task(task, mock_db)
|
|
|
|
# Verify result
|
|
assert result['analyzed_count'] == 100
|
|
assert result['status'] == 'success'
|
|
assert result['metrics']['total_count'] == 100
|
|
assert result['metrics']['positive_count'] == 60
|
|
|
|
@patch('app.workers.sentiment_worker.process_reddit_post_batch')
|
|
@patch('app.workers.sentiment_worker.get_sentiment_by_entity')
|
|
def test_execute_sentiment_analysis_task_reddit(
|
|
self,
|
|
mock_get_sentiment,
|
|
mock_process_batch
|
|
):
|
|
"""Test executing a Reddit sentiment analysis task."""
|
|
# Create worker
|
|
worker = SentimentWorker()
|
|
|
|
# Mock database session
|
|
mock_db = Mock(spec=Session)
|
|
|
|
# Mock Reddit post query
|
|
mock_posts = [Mock()] * 50
|
|
mock_db.query.return_value.filter.return_value.all.return_value = mock_posts
|
|
|
|
# Mock existing sentiment (none exist)
|
|
mock_get_sentiment.return_value = None
|
|
|
|
# Mock batch processing
|
|
mock_process_batch.return_value = [Mock()] * 50
|
|
|
|
# Mock calculate metrics
|
|
with patch.object(
|
|
worker,
|
|
'_calculate_sentiment_metrics',
|
|
return_value={
|
|
'total_count': 50,
|
|
'positive_count': 25,
|
|
'negative_count': 15,
|
|
'neutral_count': 10,
|
|
'average_compound': 0.2
|
|
}
|
|
):
|
|
# Execute task
|
|
task = {
|
|
'match_id': 456,
|
|
'source': 'reddit',
|
|
'entity_ids': ['post1', 'post2']
|
|
}
|
|
|
|
result = worker.execute_sentiment_analysis_task(task, mock_db)
|
|
|
|
# Verify result
|
|
assert result['analyzed_count'] == 50
|
|
assert result['status'] == 'success'
|
|
assert result['metrics']['total_count'] == 50
|
|
|
|
@patch('app.workers.sentiment_worker.get_sentiment_by_entity')
|
|
def test_execute_sentiment_analysis_task_all_analyzed(
|
|
self,
|
|
mock_get_sentiment
|
|
):
|
|
"""Test executing task when all items already analyzed."""
|
|
worker = SentimentWorker()
|
|
mock_db = Mock(spec=Session)
|
|
|
|
# Mock tweets
|
|
mock_tweets = [Mock()] * 100
|
|
mock_db.query.return_value.filter.return_value.all.return_value = mock_tweets
|
|
|
|
# Mock existing sentiment (all exist)
|
|
mock_get_sentiment.return_value = Mock()
|
|
|
|
# Mock calculate metrics from existing
|
|
with patch.object(
|
|
worker,
|
|
'_calculate_metrics_from_existing',
|
|
return_value={
|
|
'total_count': 100,
|
|
'average_compound': 0.4
|
|
}
|
|
):
|
|
# Execute task
|
|
task = {
|
|
'match_id': 123,
|
|
'source': 'twitter',
|
|
'entity_ids': ['tweet1', 'tweet2']
|
|
}
|
|
|
|
result = worker.execute_sentiment_analysis_task(task, mock_db)
|
|
|
|
# Verify result (0 new items analyzed)
|
|
assert result['analyzed_count'] == 0
|
|
assert result['status'] == 'success'
|
|
|
|
def test_execute_sentiment_analysis_task_unknown_source(self):
|
|
"""Test executing task with unknown source."""
|
|
worker = SentimentWorker()
|
|
mock_db = Mock(spec=Session)
|
|
|
|
# Execute task with unknown source
|
|
task = {
|
|
'match_id': 123,
|
|
'source': 'unknown',
|
|
'entity_ids': ['item1']
|
|
}
|
|
|
|
result = worker.execute_sentiment_analysis_task(task, mock_db)
|
|
|
|
# Verify error result
|
|
assert result['analyzed_count'] == 0
|
|
assert result['status'] == 'error'
|
|
assert 'error' in result
|
|
assert 'Unknown source' in result['error']
|
|
|
|
@patch('app.workers.sentiment_worker.process_tweet_batch')
|
|
@patch('app.workers.sentiment_worker.get_sentiment_by_entity')
|
|
def test_execute_sentiment_analysis_task_error_handling(
|
|
self,
|
|
mock_get_sentiment,
|
|
mock_process_batch
|
|
):
|
|
"""Test error handling in sentiment analysis."""
|
|
worker = SentimentWorker()
|
|
mock_db = Mock(spec=Session)
|
|
|
|
# Mock tweets
|
|
mock_tweets = [Mock()] * 10
|
|
mock_db.query.return_value.filter.return_value.all.return_value = mock_tweets
|
|
|
|
# Mock no existing sentiment
|
|
mock_get_sentiment.return_value = None
|
|
|
|
# Mock processing error
|
|
mock_process_batch.side_effect = Exception("Processing error")
|
|
|
|
# Execute task
|
|
task = {
|
|
'match_id': 123,
|
|
'source': 'twitter',
|
|
'entity_ids': ['tweet1', 'tweet2']
|
|
}
|
|
|
|
result = worker.execute_sentiment_analysis_task(task, mock_db)
|
|
|
|
# Verify error handling
|
|
assert result['analyzed_count'] == 0
|
|
assert result['status'] == 'error'
|
|
assert 'error' in result
|
|
|
|
@patch('app.workers.sentiment_worker.get_sentiment_by_entity')
|
|
def test_execute_twitter_sentiment_analysis_no_tweets(
|
|
self,
|
|
mock_get_sentiment
|
|
):
|
|
"""Test Twitter sentiment analysis when no tweets found."""
|
|
worker = SentimentWorker()
|
|
mock_db = Mock(spec=Session)
|
|
|
|
# Mock no tweets
|
|
mock_db.query.return_value.filter.return_value.all.return_value = []
|
|
|
|
# Execute task
|
|
result = worker._execute_twitter_sentiment_analysis(
|
|
match_id=123,
|
|
entity_ids=['tweet1', 'tweet2'],
|
|
db=mock_db
|
|
)
|
|
|
|
# Verify result
|
|
assert result['analyzed_count'] == 0
|
|
assert result['status'] == 'success'
|
|
assert result['metrics']['total_count'] == 0
|
|
|
|
|
|
class TestCreateSentimentWorker:
|
|
"""Tests for create_sentiment_worker factory function."""
|
|
|
|
def test_create_sentiment_worker(self):
|
|
"""Test creating a sentiment worker."""
|
|
worker = create_sentiment_worker()
|
|
|
|
assert isinstance(worker, SentimentWorker)
|