Add comprehensive tests for scheduled task repository, scheduler service, and task handlers

- Implemented tests for ScheduledTaskRepository covering task creation, retrieval, filtering, and status updates.
- Developed tests for SchedulerService including task creation, cancellation, user task retrieval, and maintenance jobs.
- Created tests for TaskHandlerRegistry to validate task execution for various types, including credit recharge and sound playback.
- Ensured proper error handling and edge cases in task execution scenarios.
- Added fixtures and mocks to facilitate isolated testing of services and repositories.
This commit is contained in:
JSC
2025-08-28 22:37:43 +02:00
parent 7dee6e320e
commit 03abed6d39
23 changed files with 3415 additions and 103 deletions

View File

@@ -0,0 +1,220 @@
"""Tests for scheduled task model."""
import uuid
from datetime import datetime, timedelta
import pytest
from app.models.scheduled_task import (
RecurrenceType,
ScheduledTask,
TaskStatus,
TaskType,
)
class TestScheduledTaskModel:
"""Test cases for scheduled task model."""
def test_task_creation(self):
"""Test basic task creation."""
task = ScheduledTask(
name="Test Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
)
assert task.name == "Test Task"
assert task.task_type == TaskType.CREDIT_RECHARGE
assert task.status == TaskStatus.PENDING
assert task.timezone == "UTC"
assert task.recurrence_type == RecurrenceType.NONE
assert task.parameters == {}
assert task.user_id is None
assert task.executions_count == 0
assert task.is_active is True
def test_task_with_user(self):
"""Test task creation with user association."""
user_id = uuid.uuid4()
task = ScheduledTask(
name="User Task",
task_type=TaskType.PLAY_SOUND,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
user_id=user_id,
)
assert task.user_id == user_id
assert not task.is_system_task()
def test_system_task(self):
"""Test system task (no user association)."""
task = ScheduledTask(
name="System Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
)
assert task.user_id is None
assert task.is_system_task()
def test_recurring_task(self):
"""Test recurring task properties."""
task = ScheduledTask(
name="Recurring Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
recurrence_type=RecurrenceType.DAILY,
recurrence_count=5,
)
assert task.is_recurring()
assert task.should_repeat()
def test_non_recurring_task(self):
"""Test non-recurring task properties."""
task = ScheduledTask(
name="One-shot Task",
task_type=TaskType.PLAY_SOUND,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
recurrence_type=RecurrenceType.NONE,
)
assert not task.is_recurring()
assert not task.should_repeat()
def test_infinite_recurring_task(self):
"""Test infinitely recurring task."""
task = ScheduledTask(
name="Infinite Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
recurrence_type=RecurrenceType.DAILY,
recurrence_count=None, # Infinite
)
assert task.is_recurring()
assert task.should_repeat()
# Even after many executions
task.executions_count = 100
assert task.should_repeat()
def test_recurring_task_execution_limit(self):
"""Test recurring task with execution limit."""
task = ScheduledTask(
name="Limited Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
recurrence_type=RecurrenceType.DAILY,
recurrence_count=3,
)
assert task.should_repeat()
# After 3 executions, should not repeat
task.executions_count = 3
assert not task.should_repeat()
# After more than limit, still should not repeat
task.executions_count = 5
assert not task.should_repeat()
def test_task_expiration(self):
"""Test task expiration."""
# Non-expired task
task = ScheduledTask(
name="Valid Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
expires_at=datetime.utcnow() + timedelta(hours=2),
)
assert not task.is_expired()
# Expired task
expired_task = ScheduledTask(
name="Expired Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
expires_at=datetime.utcnow() - timedelta(hours=1),
)
assert expired_task.is_expired()
# Task with no expiration
no_expiry_task = ScheduledTask(
name="No Expiry Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
)
assert not no_expiry_task.is_expired()
def test_task_with_parameters(self):
"""Test task with custom parameters."""
parameters = {
"sound_id": str(uuid.uuid4()),
"volume": 80,
"repeat": True,
}
task = ScheduledTask(
name="Parametrized Task",
task_type=TaskType.PLAY_SOUND,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
parameters=parameters,
)
assert task.parameters == parameters
assert task.parameters["sound_id"] == parameters["sound_id"]
assert task.parameters["volume"] == 80
assert task.parameters["repeat"] is True
def test_task_with_timezone(self):
"""Test task with custom timezone."""
task = ScheduledTask(
name="NY Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
timezone="America/New_York",
)
assert task.timezone == "America/New_York"
def test_task_with_cron_expression(self):
"""Test task with cron expression."""
cron_expr = "0 9 * * 1-5" # 9 AM on weekdays
task = ScheduledTask(
name="Cron Task",
task_type=TaskType.CREDIT_RECHARGE,
scheduled_at=datetime.utcnow() + timedelta(hours=1),
recurrence_type=RecurrenceType.CRON,
cron_expression=cron_expr,
)
assert task.recurrence_type == RecurrenceType.CRON
assert task.cron_expression == cron_expr
assert task.is_recurring()
def test_task_status_enum_values(self):
"""Test all task status enum values."""
assert TaskStatus.PENDING == "pending"
assert TaskStatus.RUNNING == "running"
assert TaskStatus.COMPLETED == "completed"
assert TaskStatus.FAILED == "failed"
assert TaskStatus.CANCELLED == "cancelled"
def test_task_type_enum_values(self):
"""Test all task type enum values."""
assert TaskType.CREDIT_RECHARGE == "credit_recharge"
assert TaskType.PLAY_SOUND == "play_sound"
assert TaskType.PLAY_PLAYLIST == "play_playlist"
def test_recurrence_type_enum_values(self):
"""Test all recurrence type enum values."""
assert RecurrenceType.NONE == "none"
assert RecurrenceType.HOURLY == "hourly"
assert RecurrenceType.DAILY == "daily"
assert RecurrenceType.WEEKLY == "weekly"
assert RecurrenceType.MONTHLY == "monthly"
assert RecurrenceType.YEARLY == "yearly"
assert RecurrenceType.CRON == "cron"