Files
openclaw-workspace/tests/test_habit_bot.py
2026-02-19 21:32:13 +09:00

162 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""
Unit tests for Habit Bot
Tests: habit tracking, food logging, data persistence
"""
import pytest
import sys
import os
import json
from datetime import datetime, timedelta
from unittest.mock import Mock, patch, MagicMock
from io import StringIO
# Add parent directory to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Test data directory
TEST_DATA_DIR = '/tmp/test_habit_bot'
os.makedirs(TEST_DATA_DIR, exist_ok=True)
@pytest.fixture
def mock_data():
"""Create mock data for testing"""
return {
'users': {},
'habits': {},
'habit_logs': {},
'food_logs': {},
'sessions': {}
}
class TestHabitBot:
"""Test habit tracking functionality"""
def test_add_habit(self, mock_data):
"""Test adding a new habit"""
habit_name = "morning workout"
# Simulate adding habit
user_id = "12345"
if user_id not in mock_data['habits']:
mock_data['habits'][user_id] = {}
mock_data['habits'][user_id][habit_name] = {
'name': habit_name,
'streak': 0,
'created_at': datetime.now().isoformat(),
'is_active': True
}
assert user_id in mock_data['habits']
assert habit_name in mock_data['habits'][user_id]
def test_habit_streak_increment(self, mock_data):
"""Test habit streak increment"""
user_id = "12345"
habit_name = "morning workout"
# Initial streak
mock_data['habits'][user_id] = {
habit_name: {
'name': habit_name,
'streak': 0,
'last_completed': None
}
}
# Increment streak
mock_data['habits'][user_id][habit_name]['streak'] += 1
mock_data['habits'][user_id][habit_name]['last_completed'] = datetime.now().isoformat()
assert mock_data['habits'][user_id][habit_name]['streak'] == 1
def test_habit_completion_reset(self, mock_data):
"""Test resetting habit streak when day changes"""
user_id = "12345"
habit_name = "morning workout"
# Set streak
mock_data['habits'][user_id] = {
habit_name: {
'name': habit_name,
'streak': 5,
'last_completed': (datetime.now() - timedelta(days=2)).isoformat()
}
}
# Check if streak should reset (more than 1 day since last completion)
last_completed = datetime.fromisoformat(mock_data['habits'][user_id][habit_name]['last_completed'])
days_since = (datetime.now() - last_completed).days
if days_since > 1:
mock_data['habits'][user_id][habit_name]['streak'] = 0
assert mock_data['habits'][user_id][habit_name]['streak'] == 0
def test_food_logging(self, mock_data):
"""Test food logging functionality"""
user_id = "12345"
food_entry = {
'food': "grilled chicken",
'calories': 300,
'protein': 50,
'carbs': 0,
'fat': 10,
'logged_at': datetime.now().isoformat()
}
if user_id not in mock_data['food_logs']:
mock_data['food_logs'][user_id] = []
mock_data['food_logs'][user_id].append(food_entry)
assert len(mock_data['food_logs'][user_id]) == 1
assert mock_data['food_logs'][user_id][0]['food'] == "grilled chicken"
assert mock_data['food_logs'][user_id][0]['calories'] == 300
def test_daily_calorie_calculation(self, mock_data):
"""Test daily calorie calculation"""
user_id = "12345"
mock_data['food_logs'][user_id] = [
{'calories': 500, 'protein': 50, 'carbs': 20, 'fat': 15},
{'calories': 700, 'protein': 70, 'carbs': 30, 'fat': 20},
{'calories': 400, 'protein': 40, 'carbs': 10, 'fat': 12}
]
total_calories = sum(entry['calories'] for entry in mock_data['food_logs'][user_id])
assert total_calories == 1600
def test_user_session_tracking(self, mock_data):
"""Test user session tracking"""
user_id = "12345"
session = {
'start_time': datetime.now().isoformat(),
'end_time': None,
'commands_executed': 0
}
mock_data['sessions'][user_id] = session
mock_data['sessions'][user_id]['commands_executed'] += 1
assert 'start_time' in mock_data['sessions'][user_id]
assert mock_data['sessions'][user_id]['commands_executed'] == 1
def test_data_persistence(self, mock_data):
"""Test mock data persistence in fixture"""
# Add multiple entries
for i in range(5):
habit_name = f"habit_{i}"
mock_data['habits']['user1'][habit_name] = {
'name': habit_name,
'streak': i,
'created_at': datetime.now().isoformat()
}
assert len(mock_data['habits']['user1']) == 5