/
pa1ch
/
FitAssistant
Обзор
Документация
Войти
/
pa1ch
/
FitAssistant
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/unit/services/test_progress.py
179 строк
6 KB
Pavel Chugaev
feat(progress): аналитика по упражнению — 1ПМ, недельный тоннаж, бейдж рекорда
14 июл 2026, 00:14
14 июл 2026, 00:14
22ac994
Код
Авторство
О чём код?
from datetime import date, timedelta from app.services.progress import ( get_exercise_progress, get_exercise_weekly_tonnage, get_measurement_history, get_workout_stats, is_weighted, ) from tests.factories import make_full_workout, make_measurement async def test_workout_stats_empty(session, user): stats = await get_workout_stats(session, user.id) assert stats.total_workouts == 0 assert stats.workouts_this_month == 0 assert stats.workouts_last_30_days == 0 assert stats.total_sets == 0 assert stats.most_frequent_exercise is None assert stats.avg_workouts_per_week == 0 async def test_workout_stats_with_data(session, user, seeded_exercises): today = date.today() await make_full_workout(session, user.id, today, [(1, [(10, 80.0), (8, 85.0)])]) await make_full_workout(session, user.id, today - timedelta(days=5), [(1, [(10, 80.0)])]) await session.commit() stats = await get_workout_stats(session, user.id) assert stats.total_workouts == 2 assert stats.workouts_last_30_days == 2 assert stats.total_sets == 3 assert stats.avg_workouts_per_week > 0 async def test_planned_workouts_excluded_from_stats(session, user, seeded_exercises): today = date.today() await make_full_workout(session, user.id, today, [(1, [(10, 80.0)])]) # A planned future workout must not count toward stats or sets. await make_full_workout( session, user.id, today + timedelta(days=3), [(1, [(10, 100.0), (10, 100.0)])], status="planned", ) await session.commit() stats = await get_workout_stats(session, user.id) assert stats.total_workouts == 1 assert stats.total_sets == 1 async def test_planned_workouts_excluded_from_exercise_progress(session, user, seeded_exercises): today = date.today() await make_full_workout(session, user.id, today, [(1, [(10, 80.0)])]) await make_full_workout( session, user.id, today + timedelta(days=3), [(1, [(10, 200.0)])], status="planned" ) await session.commit() result = await get_exercise_progress(session, user.id, 1) assert len(result) == 1 assert result[0].max_weight == 80.0 async def test_most_frequent_exercise(session, user, seeded_exercises): today = date.today() # exercise 1 appears twice, exercise 2 once await make_full_workout(session, user.id, today, [(1, [(10, 80.0)])]) await make_full_workout( session, user.id, today - timedelta(days=1), [(1, [(10, 80.0)]), (2, [(10, 60.0)])], ) await session.commit() stats = await get_workout_stats(session, user.id) assert stats.most_frequent_exercise is not None async def test_exercise_progress_empty(session, user, seeded_exercises): result = await get_exercise_progress(session, user.id, 1) assert result == [] async def test_exercise_progress_with_data(session, user, seeded_exercises): today = date.today() await make_full_workout( session, user.id, today - timedelta(days=7), [(1, [(10, 80.0), (8, 85.0)])] ) await make_full_workout(session, user.id, today, [(1, [(10, 90.0), (8, 95.0)])]) await session.commit() progress = await get_exercise_progress(session, user.id, 1) assert len(progress) == 2 assert progress[0].date < progress[1].date assert progress[1].max_weight >= 90.0 assert is_weighted(progress) async def test_bodyweight_exercise_progress_uses_reps(session, user, seeded_exercises): # Exercise 7 = "Подтягивания"; no added weight on any set (weight_kg=None). today = date.today() await make_full_workout( session, user.id, today - timedelta(days=7), [(7, [(8, None), (7, None)])] ) await make_full_workout(session, user.id, today, [(7, [(10, None), (9, None)])]) await session.commit() progress = await get_exercise_progress(session, user.id, 7) assert len(progress) == 2 assert not is_weighted(progress) # → charts should show reps, not weight assert progress[0].max_weight == 0 assert progress[1].max_reps == 10 assert progress[1].total_reps == 19 async def test_exercise_progress_estimated_1rm(session, user, seeded_exercises): # Epley: weight * (1 + reps/30), best single set that day. # (10, 80) -> 106.7 ; (8, 85) -> 107.7 => day max 107.7 today = date.today() await make_full_workout(session, user.id, today, [(1, [(10, 80.0), (8, 85.0)])]) await session.commit() progress = await get_exercise_progress(session, user.id, 1) assert progress[0].est_1rm == 107.7 async def test_bodyweight_exercise_has_zero_1rm(session, user, seeded_exercises): # Exercise 7 = "Подтягивания": no added weight, so estimated 1RM is meaningless -> 0. today = date.today() await make_full_workout(session, user.id, today, [(7, [(10, None)])]) await session.commit() progress = await get_exercise_progress(session, user.id, 7) assert progress[0].est_1rm == 0 async def test_weekly_tonnage_empty(session, user, seeded_exercises): assert await get_exercise_weekly_tonnage(session, user.id, 1) == [] async def test_weekly_tonnage_buckets_by_iso_week(session, user, seeded_exercises): # Two sessions in the same ISO week must merge; a third the next week is separate. monday = date(2024, 6, 3) # a Monday await make_full_workout(session, user.id, monday, [(1, [(10, 100.0)])]) # 1000 kg await make_full_workout( session, user.id, monday + timedelta(days=2), [(1, [(5, 100.0)])] ) # 500 await make_full_workout( session, user.id, monday + timedelta(days=7), [(1, [(10, 100.0)])] ) # 1000 await session.commit() weeks = await get_exercise_weekly_tonnage(session, user.id, 1) assert len(weeks) == 2 assert weeks[0].week_start == monday assert weeks[0].tonnage == 1500.0 assert weeks[0].total_sets == 2 assert weeks[1].week_start == monday + timedelta(days=7) assert weeks[1].tonnage == 1000.0 async def test_measurement_history_empty(session, user): result = await get_measurement_history(session, user.id) assert result == [] async def test_measurement_history_ordered(session, user): await make_measurement(session, user.id, date(2024, 1, 15), weight_kg=80.0) await make_measurement(session, user.id, date(2024, 1, 1), weight_kg=82.0) await make_measurement(session, user.id, date(2024, 1, 30), weight_kg=78.0) await session.commit() result = await get_measurement_history(session, user.id) dates = [m.date for m in result] assert dates == sorted(dates)