AI_Agro_Support/tests/test_treatments.py
Arsham Mirehvandi d1569a301f Refactor treatment history handling and enhance product filtering logic
- Updated README.md to clarify the conditions for `last_applied_treatment` and its integration into the advice JSON structure.
- Refactored job.py to utilize a new `TreatmentHistory` class for managing treatment data, improving clarity and efficiency in treatment retrieval.
- Enhanced advice_context.py to conditionally include `last_applied_treatment` based on the treatment history, ensuring no redundant queries are made.
- Modified products.py to implement logic for excluding active ingredients based on the latest treatment's interval, refining the product prefiltering process.
- Updated vector.py to ensure the SQL allowlist is applied correctly, improving the efficiency of product searches.
- Added unit tests to validate the new treatment history functionality and product filtering logic.
2026-09-20 23:38:25 +02:00

97 lines
3.6 KiB
Python

"""Unit tests for TreatmentHistory window slicing and the single 25-day load."""
from __future__ import annotations
import unittest
from datetime import date
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
from pipeline.stages.treatments import TreatmentHistory, load_treatment_history
_AS_OF = date(2026, 4, 16)
_FIELD_ID = 7216
_SPRAY_DATE = date(2026, 4, 10) # as_of-6
class TreatmentHistorySliceTests(unittest.TestCase):
def test_latest_picks_newest_day_and_keeps_tank_mix_order(self) -> None:
history = TreatmentHistory(
as_of=_AS_OF,
by_day={
date(2026, 3, 22): ["OLD"],
_SPRAY_DATE: ["LIETO", "TWINGO"],
},
)
self.assertEqual(history.latest(), (_SPRAY_DATE, ["LIETO", "TWINGO"]))
def test_latest_prefers_a_spray_inside_the_recent_window(self) -> None:
history = TreatmentHistory(
as_of=_AS_OF,
by_day={
_SPRAY_DATE: ["OLD"],
_AS_OF: ["TODAY"],
},
)
self.assertEqual(history.latest(), (_AS_OF, ["TODAY"]))
self.assertEqual(history.latest_before_recent(), (_SPRAY_DATE, ["OLD"]))
def test_recent_drops_days_older_than_five(self) -> None:
history = TreatmentHistory(
as_of=_AS_OF,
by_day={
_SPRAY_DATE: ["OLD"],
date(2026, 4, 11): ["RECENT"],
_AS_OF: ["TODAY"],
},
)
self.assertEqual(
history.recent(),
{date(2026, 4, 11): ["RECENT"], _AS_OF: ["TODAY"]},
)
def test_latest_before_recent_matches_as_of_minus_25_to_minus_6(self) -> None:
history = TreatmentHistory(
as_of=_AS_OF,
by_day={
date(2026, 3, 22): ["OLD"],
_SPRAY_DATE: ["LIETO"],
date(2026, 4, 11): ["RECENT"],
},
)
self.assertEqual(history.latest_before_recent(), (_SPRAY_DATE, ["LIETO"]))
def test_latest_and_latest_before_recent_return_none_when_empty(self) -> None:
history = TreatmentHistory(as_of=_AS_OF, by_day={})
self.assertIsNone(history.latest())
self.assertIsNone(history.latest_before_recent())
self.assertEqual(history.recent(), {})
class LoadTreatmentHistoryTests(unittest.TestCase):
def test_queries_as_of_minus_25_through_as_of(self) -> None:
rows = [
SimpleNamespace(rilop_date=date(2026, 3, 22), prodgov_name="OLD"),
SimpleNamespace(rilop_date=_SPRAY_DATE, prodgov_name="LIETO"),
SimpleNamespace(rilop_date=_SPRAY_DATE, prodgov_name="TWINGO"),
SimpleNamespace(rilop_date=_SPRAY_DATE, prodgov_name="LIETO"),
]
with patch("pipeline.stages.treatments.fetch_all", return_value=rows) as fetch:
history = load_treatment_history(MagicMock(), _FIELD_ID, _AS_OF)
params = fetch.call_args[0][2]
self.assertEqual(params[1], date(2026, 3, 22)) # as_of-25
self.assertEqual(params[2], _AS_OF)
self.assertEqual(history.latest(), (_SPRAY_DATE, ["LIETO", "TWINGO"]))
self.assertEqual(history.latest_before_recent(), (_SPRAY_DATE, ["LIETO", "TWINGO"]))
self.assertEqual(history.recent(), {})
def test_returns_empty_history_when_no_rows(self) -> None:
with patch("pipeline.stages.treatments.fetch_all", return_value=[]):
history = load_treatment_history(MagicMock(), _FIELD_ID, _AS_OF)
self.assertEqual(history.by_day, {})
self.assertIsNone(history.latest())
if __name__ == "__main__":
unittest.main()