Files
Ai/weather/test_adapters.py
T
2026-04-29 01:27:29 +03:30

104 lines
3.7 KiB
Python

from __future__ import annotations
from django.apps import apps
from django.test import SimpleTestCase, TestCase, override_settings
from location_data.models import SoilLocation
from weather.adapters import MockWeatherAdapter, OpenMeteoWeatherAdapter
from weather.models import WeatherForecast
from weather.services import fetch_weather_from_api, update_weather_for_location
class MockWeatherAdapterTests(SimpleTestCase):
def setUp(self):
self.adapter = MockWeatherAdapter(delay_seconds=0)
def test_same_coordinate_returns_same_forecast(self):
first = self.adapter.fetch_forecast(35.71, 51.4)
second = self.adapter.fetch_forecast(35.71, 51.4)
self.assertEqual(first, second)
def test_nearby_coordinates_produce_nearby_forecast(self):
first = self.adapter.fetch_forecast(35.71, 51.4)
second = self.adapter.fetch_forecast(35.715, 51.405)
first_daily = first["daily"]
second_daily = second["daily"]
self.assertLess(
abs(first_daily["temperature_2m_mean"][0] - second_daily["temperature_2m_mean"][0]),
2.5,
)
self.assertLess(
abs(first_daily["relative_humidity_2m_mean"][0] - second_daily["relative_humidity_2m_mean"][0]),
8.0,
)
self.assertLess(
abs(first_daily["wind_speed_10m_max"][0] - second_daily["wind_speed_10m_max"][0]),
6.0,
)
def test_shape_matches_open_meteo_daily_contract(self):
forecast = self.adapter.fetch_forecast(35.71, 51.4)
daily = forecast["daily"]
self.assertEqual(len(daily["time"]), 7)
self.assertEqual(len(daily["temperature_2m_max"]), 7)
self.assertEqual(len(daily["weather_code"]), 7)
class WeatherAdapterSelectionTests(SimpleTestCase):
def tearDown(self):
apps.get_app_config("weather").__dict__.pop("weather_data_adapter", None)
@override_settings(WEATHER_DATA_PROVIDER="mock", WEATHER_MOCK_DELAY_SECONDS=0)
def test_app_config_returns_mock_adapter(self):
config = apps.get_app_config("weather")
config.__dict__.pop("weather_data_adapter", None)
adapter = config.get_weather_data_adapter()
self.assertIsInstance(adapter, MockWeatherAdapter)
@override_settings(WEATHER_DATA_PROVIDER="open-meteo", WEATHER_TIMEOUT_SECONDS=12)
def test_app_config_returns_live_adapter(self):
config = apps.get_app_config("weather")
config.__dict__.pop("weather_data_adapter", None)
adapter = config.get_weather_data_adapter()
self.assertIsInstance(adapter, OpenMeteoWeatherAdapter)
self.assertEqual(adapter.timeout, 12)
@override_settings(WEATHER_DATA_PROVIDER="mock", WEATHER_MOCK_DELAY_SECONDS=0)
class WeatherServiceTests(TestCase):
def setUp(self):
self.location = SoilLocation.objects.create(
latitude="35.710000",
longitude="51.400000",
)
def test_fetch_weather_from_api_uses_mock_provider(self):
payload = fetch_weather_from_api(35.71, 51.4)
self.assertIn("daily", payload)
self.assertEqual(len(payload["daily"]["time"]), 7)
def test_update_weather_for_location_persists_seven_days(self):
result = update_weather_for_location(self.location)
self.assertEqual(result["status"], "success")
self.assertEqual(result["days_updated"], 7)
self.assertEqual(
WeatherForecast.objects.filter(location=self.location).count(),
7,
)
self.assertTrue(
WeatherForecast.objects.filter(
location=self.location,
precipitation__isnull=False,
weather_code__isnull=False,
).exists()
)