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

395 lines
13 KiB
Python

"""
Tests for Energy Service.
This module tests the energy service business logic including:
- Energy score calculation and storage
- Retrieval of energy scores
- Updating and deleting energy scores
- Filtering and querying
"""
import pytest
from datetime import datetime
from app.services.energy_service import (
calculate_and_store_energy_score,
get_energy_score,
get_energy_scores_by_match,
get_energy_scores_by_team,
get_energy_score_by_match_and_team,
update_energy_score,
delete_energy_score,
list_energy_scores
)
from app.schemas.energy_score import EnergyScoreCalculationRequest, EnergyScoreUpdate
class TestCalculateAndStoreEnergyScore:
"""Test energy score calculation and storage."""
def test_calculate_and_store_with_all_sources(self, db_session):
"""Test calculation and storage with all sources available."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
],
reddit_sentiments=[
{'compound': 0.3, 'positive': 0.4, 'negative': 0.3, 'neutral': 0.3, 'sentiment': 'positive'}
],
rss_sentiments=[
{'compound': 0.4, 'positive': 0.5, 'negative': 0.2, 'neutral': 0.3, 'sentiment': 'positive'}
]
)
# Act
energy_score = calculate_and_store_energy_score(db_session, request)
# Assert
assert energy_score is not None
assert energy_score.match_id == 1
assert energy_score.team_id == 1
assert 0 <= energy_score.score <= 100
assert energy_score.confidence > 0
assert len(energy_score.sources_used) == 3
assert energy_score.twitter_score is not None
assert energy_score.reddit_score is not None
assert energy_score.rss_score is not None
def test_calculate_and_store_with_twitter_only(self, db_session):
"""Test calculation and storage with only Twitter source."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
# Act
energy_score = calculate_and_store_energy_score(db_session, request)
# Assert
assert energy_score is not None
assert energy_score.match_id == 1
assert energy_score.team_id == 1
assert len(energy_score.sources_used) == 1
assert 'twitter' in energy_score.sources_used
assert energy_score.twitter_score is not None
assert energy_score.reddit_score is None
assert energy_score.rss_score is None
# Lower confidence in degraded mode
assert energy_score.confidence < 0.7
def test_calculate_and_store_no_sentiment_data(self, db_session):
"""Test calculation with no sentiment data."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[],
reddit_sentiments=[],
rss_sentiments=[]
)
# Act
energy_score = calculate_and_store_energy_score(db_session, request)
# Assert
assert energy_score is not None
assert energy_score.score == 0.0
assert energy_score.confidence == 0.0
assert len(energy_score.sources_used) == 0
class TestGetEnergyScore:
"""Test retrieval of energy scores."""
def test_get_energy_score_by_id(self, db_session):
"""Test retrieving energy score by ID."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
created = calculate_and_store_energy_score(db_session, request)
# Act
retrieved = get_energy_score(db_session, created.id)
# Assert
assert retrieved is not None
assert retrieved.id == created.id
assert retrieved.match_id == created.match_id
assert retrieved.team_id == created.team_id
assert retrieved.score == created.score
def test_get_energy_score_not_found(self, db_session):
"""Test retrieving non-existent energy score."""
# Act
retrieved = get_energy_score(db_session, 99999)
# Assert
assert retrieved is None
class TestGetEnergyScoresByMatch:
"""Test retrieval of energy scores by match."""
def test_get_energy_scores_by_match_id(self, db_session):
"""Test retrieving all energy scores for a specific match."""
# Arrange
# Create energy scores for different matches
for match_id in [1, 1, 2]:
request = EnergyScoreCalculationRequest(
match_id=match_id,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
calculate_and_store_energy_score(db_session, request)
# Act
scores_for_match_1 = get_energy_scores_by_match(db_session, 1)
scores_for_match_2 = get_energy_scores_by_match(db_session, 2)
# Assert
assert len(scores_for_match_1) == 2
assert all(score.match_id == 1 for score in scores_for_match_1)
assert len(scores_for_match_2) == 1
assert scores_for_match_2[0].match_id == 2
class TestGetEnergyScoresByTeam:
"""Test retrieval of energy scores by team."""
def test_get_energy_scores_by_team_id(self, db_session):
"""Test retrieving all energy scores for a specific team."""
# Arrange
# Create energy scores for different teams
for team_id in [1, 1, 2]:
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=team_id,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
calculate_and_store_energy_score(db_session, request)
# Act
scores_for_team_1 = get_energy_scores_by_team(db_session, 1)
scores_for_team_2 = get_energy_scores_by_team(db_session, 2)
# Assert
assert len(scores_for_team_1) == 2
assert all(score.team_id == 1 for score in scores_for_team_1)
assert len(scores_for_team_2) == 1
assert scores_for_team_2[0].team_id == 2
class TestGetEnergyScoreByMatchAndTeam:
"""Test retrieval of most recent energy score by match and team."""
def test_get_energy_score_by_match_and_team(self, db_session):
"""Test retrieving most recent energy score for match and team."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
calculate_and_store_energy_score(db_session, request)
# Act
retrieved = get_energy_score_by_match_and_team(db_session, 1, 1)
# Assert
assert retrieved is not None
assert retrieved.match_id == 1
assert retrieved.team_id == 1
def test_get_energy_score_by_match_and_team_not_found(self, db_session):
"""Test retrieving non-existent energy score."""
# Act
retrieved = get_energy_score_by_match_and_team(db_session, 999, 999)
# Assert
assert retrieved is None
class TestUpdateEnergyScore:
"""Test updating energy scores."""
def test_update_energy_score(self, db_session):
"""Test updating an existing energy score."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
created = calculate_and_store_energy_score(db_session, request)
# Act
update = EnergyScoreUpdate(
score=75.0,
confidence=0.9
)
updated = update_energy_score(db_session, created.id, update)
# Assert
assert updated is not None
assert updated.id == created.id
assert updated.score == 75.0
assert updated.confidence == 0.9
assert updated.updated_at > created.updated_at
def test_update_energy_score_not_found(self, db_session):
"""Test updating non-existent energy score."""
# Arrange
update = EnergyScoreUpdate(score=75.0, confidence=0.9)
# Act
updated = update_energy_score(db_session, 99999, update)
# Assert
assert updated is None
class TestDeleteEnergyScore:
"""Test deleting energy scores."""
def test_delete_energy_score(self, db_session):
"""Test deleting an existing energy score."""
# Arrange
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
created = calculate_and_store_energy_score(db_session, request)
# Act
deleted = delete_energy_score(db_session, created.id)
# Assert
assert deleted is True
retrieved = get_energy_score(db_session, created.id)
assert retrieved is None
def test_delete_energy_score_not_found(self, db_session):
"""Test deleting non-existent energy score."""
# Act
deleted = delete_energy_score(db_session, 99999)
# Assert
assert deleted is False
class TestListEnergyScores:
"""Test listing and filtering energy scores."""
def test_list_energy_scores_default(self, db_session):
"""Test listing energy scores with default parameters."""
# Arrange
for i in range(5):
request = EnergyScoreCalculationRequest(
match_id=i,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
calculate_and_store_energy_score(db_session, request)
# Act
scores = list_energy_scores(db_session)
# Assert
assert len(scores) == 5
def test_list_energy_scores_with_match_filter(self, db_session):
"""Test listing energy scores filtered by match ID."""
# Arrange
for match_id in [1, 1, 2]:
request = EnergyScoreCalculationRequest(
match_id=match_id,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
calculate_and_store_energy_score(db_session, request)
# Act
scores = list_energy_scores(db_session, match_id=1)
# Assert
assert len(scores) == 2
assert all(score.match_id == 1 for score in scores)
def test_list_energy_scores_with_score_filter(self, db_session):
"""Test listing energy scores filtered by score range."""
# Arrange
for score in [30.0, 50.0, 70.0, 90.0]:
request = EnergyScoreCalculationRequest(
match_id=1,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
created = calculate_and_store_energy_score(db_session, request)
# Manually update score for testing
created.score = score
db_session.commit()
# Act
scores = list_energy_scores(db_session, min_score=40.0, max_score=80.0)
# Assert
assert len(scores) == 2
assert all(40.0 <= score.score <= 80.0 for score in scores)
def test_list_energy_scores_with_pagination(self, db_session):
"""Test listing energy scores with pagination."""
# Arrange
for i in range(10):
request = EnergyScoreCalculationRequest(
match_id=i,
team_id=1,
twitter_sentiments=[
{'compound': 0.5, 'positive': 0.6, 'negative': 0.2, 'neutral': 0.2, 'sentiment': 'positive'}
]
)
calculate_and_store_energy_score(db_session, request)
# Act
page1 = list_energy_scores(db_session, limit=5, offset=0)
page2 = list_energy_scores(db_session, limit=5, offset=5)
# Assert
assert len(page1) == 5
assert len(page2) == 5
# Verify no overlap
page1_ids = [score.id for score in page1]
page2_ids = [score.id for score in page2]
assert set(page1_ids).isdisjoint(set(page2_ids))
if __name__ == '__main__':
pytest.main([__file__, '-v'])