import unittest from app.services.running_coaching import build_run_analysis, build_running_profile class RunningCoachingTests(unittest.TestCase): def test_prioritizes_high_load_and_low_cadence(self): analysis = build_run_analysis( { "sample_count": 80, "avg_heart_rate_bpm": 154, "heart_rate_rise_bpm": 16, "avg_cadence_spm": 142, "avg_ground_contact_time_ms": 330, "avg_vertical_oscillation_cm": 11.4, "avg_left_right_asymmetry_pct": 9.2, } ) self.assertEqual([item["key"] for item in analysis["focus"]], ["heart_rate", "cadence"]) self.assertIn("보폭", analysis["focus"][1]["action"]) def test_does_not_warn_when_form_values_are_stable(self): analysis = build_run_analysis( { "sample_count": 80, "avg_heart_rate_bpm": 148, "avg_cadence_spm": 170, "avg_ground_contact_time_ms": 280, "avg_vertical_oscillation_cm": 8.0, "avg_left_right_asymmetry_pct": 3.1, } ) self.assertEqual(analysis["focus"], []) self.assertGreaterEqual(len(analysis["strengths"]), 2) def test_profile_uses_repeated_sensor_records(self): profile = build_running_profile( [ {"sensor_summary": {"avg_cadence_spm": 142, "avg_ground_contact_time_ms": 325}}, {"sensor_summary": {"avg_cadence_spm": 145, "avg_ground_contact_time_ms": 320}}, {"sensor_summary": {"avg_cadence_spm": 148, "avg_ground_contact_time_ms": 315}}, ] ) self.assertEqual(profile["status"], "ready") self.assertEqual(profile["next_focus"]["title"], "러닝 리듬") self.assertEqual(profile["sample_size"], 3) def test_heart_rate_only_records_do_not_ready_form_profile(self): profile = build_running_profile( [ {"sensor_summary": {"avg_heart_rate_bpm": 145}}, {"sensor_summary": {"avg_heart_rate_bpm": 148}}, {"sensor_summary": {"avg_heart_rate_bpm": 150}}, ] ) self.assertEqual(profile["status"], "collecting") self.assertEqual(profile["sample_size"], 0) if __name__ == "__main__": unittest.main()