chartbastan/backend/tests/test_sentiment_analyzer.py
2026-02-01 09:31:38 +01:00

202 lines
7.1 KiB
Python

"""
Tests for Sentiment Analyzer
This module tests the VADER sentiment analyzer functionality.
"""
import pytest
from app.ml.sentiment_analyzer import (
analyze_sentiment,
analyze_sentiment_batch,
calculate_aggregated_metrics,
classify_sentiment,
test_analyzer_performance
)
class TestClassifySentiment:
"""Test sentiment classification based on compound score."""
def test_positive_classification(self):
"""Test classification of positive sentiment."""
assert classify_sentiment(0.5) == 'positive'
assert classify_sentiment(0.05) == 'positive'
assert classify_sentiment(1.0) == 'positive'
def test_negative_classification(self):
"""Test classification of negative sentiment."""
assert classify_sentiment(-0.5) == 'negative'
assert classify_sentiment(-0.05) == 'negative'
assert classify_sentiment(-1.0) == 'negative'
def test_neutral_classification(self):
"""Test classification of neutral sentiment."""
assert classify_sentiment(0.0) == 'neutral'
assert classify_sentiment(0.04) == 'neutral'
assert classify_sentiment(-0.04) == 'neutral'
class TestAnalyzeSentiment:
"""Test single text sentiment analysis."""
def test_positive_text(self):
"""Test analysis of positive text."""
text = "I love this game! It's absolutely amazing and wonderful!"
result = analyze_sentiment(text)
assert result['sentiment'] == 'positive'
assert result['compound'] > 0.05
assert 0 <= result['positive'] <= 1
assert 0 <= result['negative'] <= 1
assert 0 <= result['neutral'] <= 1
def test_negative_text(self):
"""Test analysis of negative text."""
text = "This is terrible! I hate it and it's the worst ever."
result = analyze_sentiment(text)
assert result['sentiment'] == 'negative'
assert result['compound'] < -0.05
assert 0 <= result['positive'] <= 1
assert 0 <= result['negative'] <= 1
assert 0 <= result['neutral'] <= 1
def test_neutral_text(self):
"""Test analysis of neutral text."""
text = "The game is okay. Nothing special but nothing bad."
result = analyze_sentiment(text)
assert result['sentiment'] in ['positive', 'negative', 'neutral']
assert 0 <= result['compound'] <= 1
assert 0 <= result['positive'] <= 1
assert 0 <= result['negative'] <= 1
assert 0 <= result['neutral'] <= 1
def test_empty_text_raises_error(self):
"""Test that empty text raises ValueError."""
with pytest.raises(ValueError):
analyze_sentiment("")
def test_invalid_input_raises_error(self):
"""Test that invalid input raises ValueError."""
with pytest.raises(ValueError):
analyze_sentiment(None)
with pytest.raises(ValueError):
analyze_sentiment(123)
class TestAnalyzeSentimentBatch:
"""Test batch sentiment analysis."""
def test_batch_analysis_multiple_texts(self):
"""Test analysis of multiple texts."""
texts = [
"I love this!",
"This is terrible!",
"It's okay."
]
results = analyze_sentiment_batch(texts)
assert len(results) == 3
assert all('compound' in r for r in results)
assert all('positive' in r for r in results)
assert all('negative' in r for r in results)
assert all('neutral' in r for r in results)
assert all('sentiment' in r for r in results)
def test_batch_analysis_empty_list(self):
"""Test batch analysis with empty list."""
results = analyze_sentiment_batch([])
assert results == []
def test_batch_analysis_with_errors(self):
"""Test batch analysis handles errors gracefully."""
texts = [
"This is good!",
"", # Invalid - should be handled gracefully
"This is great!"
]
results = analyze_sentiment_batch(texts)
assert len(results) == 3
# The invalid text should return neutral sentiment
assert results[1]['sentiment'] == 'neutral'
assert results[1]['compound'] == 0.0
class TestCalculateAggregatedMetrics:
"""Test calculation of aggregated sentiment metrics."""
def test_aggregated_metrics_empty_list(self):
"""Test aggregated metrics with empty list."""
metrics = calculate_aggregated_metrics([])
assert metrics['total_count'] == 0
assert metrics['positive_count'] == 0
assert metrics['negative_count'] == 0
assert metrics['neutral_count'] == 0
assert metrics['positive_ratio'] == 0.0
assert metrics['negative_ratio'] == 0.0
assert metrics['neutral_ratio'] == 0.0
assert metrics['average_compound'] == 0.0
def test_aggregated_metrics_all_positive(self):
"""Test aggregated metrics with all positive sentiments."""
sentiments = [
{'compound': 0.5, 'sentiment': 'positive'},
{'compound': 0.7, 'sentiment': 'positive'},
{'compound': 0.9, 'sentiment': 'positive'}
]
metrics = calculate_aggregated_metrics(sentiments)
assert metrics['total_count'] == 3
assert metrics['positive_count'] == 3
assert metrics['negative_count'] == 0
assert metrics['neutral_count'] == 0
assert metrics['positive_ratio'] == 1.0
assert metrics['average_compound'] == pytest.approx(0.7, rel=0.01)
def test_aggregated_metrics_mixed(self):
"""Test aggregated metrics with mixed sentiments."""
sentiments = [
{'compound': 0.5, 'sentiment': 'positive'},
{'compound': -0.5, 'sentiment': 'negative'},
{'compound': 0.0, 'sentiment': 'neutral'},
{'compound': 0.7, 'sentiment': 'positive'}
]
metrics = calculate_aggregated_metrics(sentiments)
assert metrics['total_count'] == 4
assert metrics['positive_count'] == 2
assert metrics['negative_count'] == 1
assert metrics['neutral_count'] == 1
assert metrics['positive_ratio'] == 0.5
assert metrics['negative_ratio'] == 0.25
assert metrics['neutral_ratio'] == 0.25
assert metrics['average_compound'] == pytest.approx(0.175, rel=0.01)
class TestAnalyzerPerformance:
"""Test performance of the sentiment analyzer."""
def test_performance_1000_tweets(self):
"""Test that 1000 tweets can be analyzed in less than 1 second."""
time_taken = test_analyzer_performance(1000)
assert time_taken < 1.0, f"Analysis took {time_taken:.4f}s, expected < 1.0s"
def test_performance_5000_tweets(self):
"""Test performance with 5000 tweets."""
time_taken = test_analyzer_performance(5000)
# Should still be fast, but we allow some scaling
assert time_taken < 5.0, f"Analysis took {time_taken:.4f}s, expected < 5.0s"
def test_performance_10000_tweets(self):
"""Test performance with 10000 tweets."""
time_taken = test_analyzer_performance(10000)
# Should still be very fast
assert time_taken < 10.0, f"Analysis took {time_taken:.4f}s, expected < 10.0s"