SkillSprout / tests /test_gamification.py
shyamsridhar123
Deploy SkillSprout to HF Spaces - Clean version without large media files
5f613ea
"""
Tests for the gamification system in SkillSprout
"""
import pytest
from unittest.mock import Mock, patch
import sys
import os
# Add parent directory to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from space_app import (
GamificationManager, Achievement, UserStats, EnhancedUserProgress
)
class TestAchievement:
"""Test cases for Achievement data class"""
def test_achievement_creation(self):
"""Test creating an achievement"""
achievement = Achievement(
id="test_achievement",
name="Test Achievement",
description="A test achievement",
icon="๐Ÿ†",
unlocked=False,
unlock_condition="Complete 1 lesson"
)
assert achievement.id == "test_achievement"
assert achievement.name == "Test Achievement"
assert achievement.unlocked is False
assert achievement.icon == "๐Ÿ†"
def test_achievement_defaults(self):
"""Test achievement with default values"""
achievement = Achievement(
id="simple",
name="Simple",
description="Simple achievement",
icon="โญ"
)
assert achievement.unlocked is False
assert achievement.unlock_condition == ""
class TestUserStats:
"""Test cases for UserStats class"""
def test_user_stats_creation(self):
"""Test creating user stats"""
stats = UserStats(user_id="test_user")
assert stats.user_id == "test_user"
assert stats.total_points == 0
assert stats.level == 1
assert stats.achievements == []
assert stats.streak_days == 0
assert stats.total_lessons == 0
assert stats.total_quizzes == 0
assert stats.correct_answers == 0
def test_add_points_no_level_up(self):
"""Test adding points without level up"""
stats = UserStats(user_id="test_user")
# Act
stats.add_points(50)
# Assert
assert stats.total_points == 50
assert stats.level == 1 # Should still be level 1
def test_add_points_level_up(self):
"""Test adding points that triggers level up"""
stats = UserStats(user_id="test_user")
# Act
stats.add_points(150) # Should trigger level up
# Assert
assert stats.total_points == 150
assert stats.level == 2
def test_add_points_multiple_levels(self):
"""Test adding points that triggers multiple level ups"""
stats = UserStats(user_id="test_user")
# Act
stats.add_points(450) # Should reach level 5
# Assert
assert stats.total_points == 450
assert stats.level == 5
def test_add_points_max_level(self):
"""Test that level doesn't exceed maximum"""
stats = UserStats(user_id="test_user")
# Act
stats.add_points(2000) # Way more than needed for max level
# Assert
assert stats.level == 10 # Should cap at level 10
def test_get_accuracy_no_quizzes(self):
"""Test accuracy calculation with no quizzes"""
stats = UserStats(user_id="test_user")
# Act & Assert
assert stats.get_accuracy() == 0.0
def test_get_accuracy_with_quizzes(self):
"""Test accuracy calculation with quiz data"""
stats = UserStats(user_id="test_user")
stats.total_quizzes = 10
stats.correct_answers = 8
# Act
accuracy = stats.get_accuracy()
# Assert
assert accuracy == 80.0
class TestEnhancedUserProgress:
"""Test cases for EnhancedUserProgress class"""
def test_enhanced_progress_creation(self):
"""Test creating enhanced user progress"""
progress = EnhancedUserProgress(
user_id="test_user",
skill="Python Programming"
)
assert progress.user_id == "test_user"
assert progress.skill == "Python Programming"
assert progress.lessons_completed == 0
assert progress.quiz_scores == []
assert progress.time_spent == []
assert progress.mastery_level == 0.0
class TestGamificationManager:
"""Test cases for GamificationManager class"""
@pytest.fixture
def gamification_manager(self):
"""Create a GamificationManager instance for testing"""
return GamificationManager()
def test_gamification_manager_initialization(self, gamification_manager):
"""Test GamificationManager initialization"""
assert len(gamification_manager.user_stats) == 0
assert len(gamification_manager.achievements) > 0
# Check that all required achievements exist
required_achievements = [
"first_steps", "quiz_master", "persistent", "scholar",
"expert", "polyglot", "perfectionist", "speed",
"consistent", "explorer"
]
for achievement_id in required_achievements:
assert achievement_id in gamification_manager.achievements
def test_get_user_stats_new_user(self, gamification_manager):
"""Test getting stats for a new user"""
# Act
stats = gamification_manager.get_user_stats("new_user")
# Assert
assert isinstance(stats, UserStats)
assert stats.user_id == "new_user"
assert stats.total_points == 0
assert stats.level == 1
def test_get_user_stats_existing_user(self, gamification_manager):
"""Test getting stats for existing user"""
# Arrange
user_id = "existing_user"
stats1 = gamification_manager.get_user_stats(user_id)
stats1.total_points = 100
# Act
stats2 = gamification_manager.get_user_stats(user_id)
# Assert
assert stats2.total_points == 100
assert stats1 is stats2 # Should be same object
def test_check_achievements_first_steps(self, gamification_manager):
"""Test unlocking first steps achievement"""
# Arrange
user_id = "test_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
# Set up conditions for first steps achievement
stats = gamification_manager.get_user_stats(user_id)
stats.total_lessons = 1
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
assert len(newly_unlocked) > 0
achievement_ids = [a.id for a in newly_unlocked]
assert "first_steps" in achievement_ids
assert "first_steps" in stats.achievements
def test_check_achievements_quiz_master(self, gamification_manager):
"""Test unlocking quiz master achievement"""
# Arrange
user_id = "quiz_master_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
progress.quiz_scores = [100, 80, 100] # Has perfect score
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "quiz_master" in achievement_ids
def test_check_achievements_persistent(self, gamification_manager):
"""Test unlocking persistent learner achievement"""
# Arrange
user_id = "persistent_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
stats = gamification_manager.get_user_stats(user_id)
stats.total_lessons = 5
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "persistent" in achievement_ids
def test_check_achievements_no_new_unlocks(self, gamification_manager):
"""Test checking achievements when none should be unlocked"""
# Arrange
user_id = "minimal_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
# User has minimal progress, shouldn't unlock anything
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
assert len(newly_unlocked) == 0
def test_check_achievements_already_unlocked(self, gamification_manager):
"""Test that already unlocked achievements aren't returned again"""
# Arrange
user_id = "repeat_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
stats = gamification_manager.get_user_stats(user_id)
stats.total_lessons = 1
stats.achievements = ["first_steps"] # Already unlocked
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "first_steps" not in achievement_ids
def test_check_achievements_points_awarded(self, gamification_manager):
"""Test that bonus points are awarded for achievements"""
# Arrange
user_id = "points_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
stats = gamification_manager.get_user_stats(user_id)
initial_points = stats.total_points
stats.total_lessons = 1 # Will unlock first_steps
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
assert len(newly_unlocked) > 0
assert stats.total_points > initial_points # Should have bonus points
def test_achievement_perfectionist(self, gamification_manager):
"""Test perfectionist achievement (5 perfect scores)"""
# Arrange
user_id = "perfectionist_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
progress.quiz_scores = [100, 100, 100, 100, 100, 90] # 5 perfect scores
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "perfectionist" in achievement_ids
def test_achievement_consistent(self, gamification_manager):
"""Test consistent achievement (7-day streak)"""
# Arrange
user_id = "consistent_user"
progress = EnhancedUserProgress(user_id=user_id, skill="Python")
stats = gamification_manager.get_user_stats(user_id)
stats.streak_days = 7
# Act
newly_unlocked = gamification_manager.check_achievements(user_id, progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "consistent" in achievement_ids
@pytest.mark.integration
class TestGamificationIntegration:
"""Integration tests for gamification with other systems"""
def test_gamification_with_lesson_completion(self):
"""Test gamification integration when completing lessons"""
# This would test the integration between the main app and gamification
# Requires importing the enhanced app components
pass
def test_gamification_with_quiz_submission(self):
"""Test gamification integration when submitting quizzes"""
pass
@pytest.mark.unit
class TestAchievementConditions:
"""Test specific achievement unlock conditions"""
@pytest.fixture
def sample_progress(self):
"""Create sample progress data for testing"""
return EnhancedUserProgress(
user_id="test_user",
skill="Python Programming",
lessons_completed=0,
quiz_scores=[],
time_spent=[],
mastery_level=0.0
)
def test_scholar_achievement_condition(self, gamification_manager, enhanced_user_progress):
"""Test scholar achievement (10 lessons)"""
# Arrange
stats = gamification_manager.get_user_stats("test_user")
stats.total_lessons = 10
# Act
newly_unlocked = gamification_manager.check_achievements("test_user", enhanced_user_progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "scholar" in achievement_ids
def test_expert_achievement_condition(self, gamification_manager, enhanced_user_progress):
"""Test expert achievement (20 lessons)"""
# Arrange
stats = gamification_manager.get_user_stats("test_user")
stats.total_lessons = 20
# Act
newly_unlocked = gamification_manager.check_achievements("test_user", enhanced_user_progress)
# Assert
achievement_ids = [a.id for a in newly_unlocked]
assert "expert" in achievement_ids
assert "scholar" in achievement_ids # Should also unlock scholar
assert "persistent" in achievement_ids # Should also unlock persistent