Files
Stride/tests/test_analytics.py
T

75 lines
2.3 KiB
Python

from types import SimpleNamespace
import pytest
from app.analytics import analyse, enrich, running_cost
def run(grade=0):
return SimpleNamespace(
sport="running",
distance_m=600,
samples=[
{
"distance": i * 3,
"time": i,
"elevation": 100 + i * 3 * grade,
"speed": 3,
"heart_rate": 150,
"cadence": 170,
}
for i in range(201)
],
laps=[{"distance": 301}, {"distance": 299}],
)
def test_flat_gap_and_laps_use_distance_weighted_time():
result = analyse(run())
assert result["summary"]["gap"] == pytest.approx(1000 / 3)
assert result["summary"]["gap_coverage"] == 100
assert [lap["gap"] for lap in result["laps"]] == pytest.approx([1000 / 3] * 2)
assert sum(lap["gap_time"] for lap in result["laps"]) == pytest.approx(200)
assert result["terrain"][1]["heart_rate"] == 150
@pytest.mark.parametrize("grade", [-0.1, 0.1])
def test_slope_adjusts_pace_using_cost_ratio(grade):
activity = run(grade)
row = enrich(activity.samples)[100]
assert row["grade"] == pytest.approx(grade * 100)
assert row["gap"] == pytest.approx(1000 / 3 * 3.6 / running_cost(grade))
gap = analyse(activity)["summary"]["gap"]
assert (gap < 1000 / 3) if grade > 0 else (gap > 1000 / 3)
def test_missing_data_and_nonrunning_do_not_invent_gap():
activity = run()
for row in activity.samples:
row["elevation"] = None
assert analyse(activity)["summary"]["gap"] is None
activity = run()
activity.sport = "cycling"
assert analyse(activity)["summary"]["gap"] is None
activity = run()
for row in activity.samples:
row["time"] = None
assert analyse(activity)["summary"]["gap"] is None
def test_recording_gap_excluded_from_time_and_distance():
activity = run()
for row in activity.samples[100:]:
row["time"] += 100
result = analyse(activity)
assert result["summary"]["gap"] == pytest.approx(1000 / 3)
assert result["summary"]["gap_coverage"] == pytest.approx(99.5)
def test_extreme_slopes_and_stationary_records_have_no_gap():
assert analyse(run(0.5))["summary"]["gap"] is None
activity = run()
for row in activity.samples:
row["distance"] = 0
assert analyse(activity)["summary"]["gap"] is None