mealgraph / tests /test_quantities_finder.py
moazeldegwy's picture
Phase 0: Foundations cleanup and test scaffold
f8381b8
"""Smoke tests for the PuLP-backed QuantitiesFinder.
Pure deterministic tool — no LLM, no network. Should be the fastest test in
the suite and the one we trust most.
"""
from __future__ import annotations
import json
from tools import QuantitiesFinder
def test_basic_two_food_balance() -> None:
"""Two foods, simple targets — solver must find quantities within a few
percent of the target."""
qf = QuantitiesFinder()
payload = {
"foods": [
{
"name": "chicken_breast",
"calories": 165,
"protein": 31,
"fat": 3.6,
"carbohydrates": 0,
"estimated_g": 200,
},
{
"name": "rice_cooked",
"calories": 130,
"protein": 2.7,
"fat": 0.3,
"carbohydrates": 28,
"estimated_g": 200,
},
],
"targets": {"calories": 700, "protein": 65, "fat": 8, "carbohydrates": 60},
}
result = json.loads(qf.handle_task(json.dumps(payload)))
assert "quantities" in result and "achieved" in result, f"Bad shape: {result}"
achieved = result["achieved"]
# The solver minimises weighted deviation across all 4 nutrients. With only
# two foods (chicken and rice) it cannot hit every target tightly — it will
# nail fat/carbs (constrained by rice) and trade off calories/protein.
# We assert it lands within 20% of every target, which is the realistic
# feasibility envelope for a 2-food problem.
for nut, target in [("calories", 700), ("protein", 65), ("fat", 8), ("carbohydrates", 60)]:
deviation = abs(achieved[nut] - target) / target
assert deviation < 0.20, f"{nut} achieved={achieved[nut]} target={target} dev={deviation:.2%}"
def test_invalid_payload_returns_error() -> None:
qf = QuantitiesFinder()
bad = {"foods": [{"name": "x"}], "targets": {}} # missing required keys
result = json.loads(qf.handle_task(json.dumps(bad)))
assert "error" in result, f"Expected an error key, got {result}"
def test_min_max_bounds_respected() -> None:
qf = QuantitiesFinder()
payload = {
"foods": [
{
"name": "egg",
"calories": 155,
"protein": 13,
"fat": 11,
"carbohydrates": 1.1,
"estimated_g": 100,
"min_g": 50,
"max_g": 120,
},
{
"name": "oats",
"calories": 389,
"protein": 17,
"fat": 7,
"carbohydrates": 66,
"estimated_g": 80,
"min_g": 30,
"max_g": 150,
},
],
"targets": {"calories": 500, "protein": 25, "fat": 15, "carbohydrates": 50},
}
result = json.loads(qf.handle_task(json.dumps(payload)))
qty = result["quantities"]
assert 50 <= qty["egg"] <= 120
assert 30 <= qty["oats"] <= 150