Spaces:
Sleeping
Sleeping
| """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 | |