- Updated the CSV import logic to support new row processing specifications for weight and vitals baseline, allowing for better data aggregation and validation. - Implemented handling for multiple rows on the same day, enabling aggregation of values such as averages for vitals and last values for weight. - Enhanced test coverage for the new import functionalities, ensuring correct behavior during data processing and validation. - Refactored the module registry to include default import row processing options for better flexibility in handling CSV data.
89 lines
2.7 KiB
Python
89 lines
2.7 KiB
Python
"""Tests für CSV-Zeilenaggregation (import_row_processing)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import datetime as dt
|
|
|
|
import pytest
|
|
|
|
from csv_parser.import_row_processing import (
|
|
aggregate_mapped_rows,
|
|
resolve_import_row_processing,
|
|
validate_import_row_processing,
|
|
)
|
|
|
|
|
|
def test_validate_rejects_unknown_aggregate():
|
|
with pytest.raises(ValueError, match="ungültige Operation"):
|
|
validate_import_row_processing(
|
|
"nutrition",
|
|
{"group_by": ["date"], "aggregates": {"kcal": "bogus"}},
|
|
{"Kal": "date", "E": "kcal"},
|
|
)
|
|
|
|
|
|
def test_validate_group_by_must_be_mapped():
|
|
with pytest.raises(ValueError, match="keiner CSV-Spalte zugeordnet"):
|
|
validate_import_row_processing(
|
|
"nutrition",
|
|
{"group_by": ["date"], "aggregates": {"kcal": "sum"}},
|
|
{"Kal": "kcal"}, # date nicht gemappt
|
|
)
|
|
|
|
|
|
def test_aggregate_mapped_rows_sums_same_group():
|
|
d = dt.date(2024, 1, 15)
|
|
rows = [
|
|
{"date": d, "kcal": 500.0, "protein_g": 20},
|
|
{"date": d, "kcal": 300.0, "protein_g": 15},
|
|
]
|
|
spec = {"group_by": ["date"], "aggregates": {"kcal": "sum", "protein_g": "sum"}}
|
|
out = aggregate_mapped_rows(rows, spec)
|
|
assert len(out) == 1
|
|
assert out[0]["kcal"] == 800.0
|
|
assert out[0]["protein_g"] == 35
|
|
|
|
|
|
def test_resolve_explicit_overrides_default():
|
|
m = {
|
|
"import_row_processing": {"group_by": ["date"], "aggregates": {"kcal": "mean"}},
|
|
}
|
|
spec = resolve_import_row_processing("nutrition", m)
|
|
assert spec is not None
|
|
assert spec["aggregates"]["kcal"] == "mean"
|
|
|
|
|
|
def test_resolve_empty_dict_falls_back_to_module_default():
|
|
m: dict = {"import_row_processing": {}}
|
|
spec = resolve_import_row_processing("nutrition", m)
|
|
assert spec is not None
|
|
assert spec["group_by"] == ["date"]
|
|
assert spec["aggregates"]["kcal"] == "sum"
|
|
|
|
|
|
def test_resolve_none_uses_nutrition_default():
|
|
spec = resolve_import_row_processing("nutrition", {})
|
|
assert spec is not None
|
|
assert "date" in (spec.get("group_by") or [])
|
|
|
|
|
|
def test_resolve_weight_default_uses_last():
|
|
spec = resolve_import_row_processing("weight", {})
|
|
assert spec is not None
|
|
assert spec.get("aggregates", {}).get("weight") == "last"
|
|
assert spec.get("aggregates", {}).get("note") == "last"
|
|
|
|
|
|
def test_validate_weight_import_row_processing_ok():
|
|
validate_import_row_processing(
|
|
"weight",
|
|
{"group_by": ["date"], "aggregates": {"weight": "mean"}},
|
|
{"D": "date", "W": "weight"},
|
|
)
|
|
|
|
|
|
def test_resolve_vitals_baseline_default_uses_mean():
|
|
spec = resolve_import_row_processing("vitals_baseline", {})
|
|
assert spec is not None
|
|
assert spec.get("aggregates", {}).get("resting_hr") == "mean"
|