Skip to content

Commit 0d324a5

Browse files
committed
TST: Add tests for new models
1 parent d4dde0d commit 0d324a5

File tree

2 files changed

+88
-4
lines changed

2 files changed

+88
-4
lines changed

tests/integration/environment/test_environment.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import time
2-
from datetime import date, datetime, timezone
2+
from datetime import date, datetime, timedelta, timezone
33
from unittest.mock import patch
44

55
import numpy as np
@@ -146,6 +146,7 @@ def test_wind_plots_wrapping_direction(mock_show, example_plain_env): # pylint:
146146
assert example_plain_env.plots.atmospheric_model() is None
147147

148148

149+
@pytest.mark.slow
149150
@pytest.mark.parametrize(
150151
"model_name",
151152
[
@@ -195,6 +196,42 @@ def test_gfs_atmosphere(mock_show, example_spaceport_env): # pylint: disable=un
195196
assert example_spaceport_env.all_info() is None
196197

197198

199+
@pytest.mark.slow
200+
@patch("matplotlib.pyplot.show")
201+
def test_aigfs_atmosphere(mock_show, example_spaceport_env): # pylint: disable=unused-argument
202+
"""Tests the Forecast model with the AIGFS file.
203+
204+
Parameters
205+
----------
206+
mock_show : mock
207+
Mock object to replace matplotlib.pyplot.show() method.
208+
example_spaceport_env : rocketpy.Environment
209+
Example environment object to be tested.
210+
"""
211+
example_spaceport_env.set_atmospheric_model(type="Forecast", file="AIGFS")
212+
assert example_spaceport_env.all_info() is None
213+
214+
215+
@pytest.mark.slow
216+
@patch("matplotlib.pyplot.show")
217+
def test_hrrr_atmosphere(mock_show, example_spaceport_env): # pylint: disable=unused-argument
218+
"""Tests the Forecast model with the HRRR file.
219+
220+
Parameters
221+
----------
222+
mock_show : mock
223+
Mock object to replace matplotlib.pyplot.show() method.
224+
example_spaceport_env : rocketpy.Environment
225+
Example environment object to be tested.
226+
"""
227+
# Sometimes the HRRR latest-model can fail due to not having at least 24
228+
# hours in the future in the forecast, so we try with 12 hours in the future
229+
# only.
230+
example_spaceport_env.set_date(datetime.now() + timedelta(hours=12))
231+
example_spaceport_env.set_atmospheric_model(type="Forecast", file="HRRR")
232+
assert example_spaceport_env.all_info() is None
233+
234+
198235
@pytest.mark.slow
199236
@patch("matplotlib.pyplot.show")
200237
def test_nam_atmosphere(mock_show, example_spaceport_env): # pylint: disable=unused-argument

tests/unit/environment/test_environment.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,8 @@ def test_resolve_dictionary_keeps_compatible_mapping(example_plain_env):
336336
assert resolved is gfs_mapping
337337

338338

339-
def test_resolve_dictionary_falls_back_to_legacy_mapping(example_plain_env):
340-
"""Fallback to a compatible built-in mapping for legacy NOMADS-style files."""
339+
def test_resolve_dictionary_falls_back_to_first_compatible_mapping(example_plain_env):
340+
"""Fallback to the first compatible built-in mapping for legacy-style files."""
341341
thredds_gfs_mapping = example_plain_env._Environment__weather_model_map.get("GFS")
342342
dataset = _DummyDataset(
343343
[
@@ -356,7 +356,6 @@ def test_resolve_dictionary_falls_back_to_legacy_mapping(example_plain_env):
356356
thredds_gfs_mapping, dataset
357357
)
358358

359-
# Explicit legacy mappings should be preferred over unrelated model mappings.
360359
assert resolved == example_plain_env._Environment__weather_model_map.get(
361360
"GFS_LEGACY"
362361
)
@@ -602,3 +601,51 @@ def test_set_atmospheric_model_raises_for_unknown_model_type(example_plain_env):
602601
# Act / Assert
603602
with pytest.raises(ValueError, match="Unknown model type"):
604603
environment.set_atmospheric_model(type="unknown_type")
604+
605+
606+
@pytest.mark.parametrize("shortcut_name", ["AIGFS", "HRRR"])
607+
def test_forecast_shortcut_and_dictionary_are_case_insensitive(
608+
monkeypatch, shortcut_name
609+
):
610+
"""Ensure forecast shortcuts and built-in dictionaries ignore input casing."""
611+
# Arrange
612+
env = Environment(date=(2026, 3, 17, 12), latitude=32.99, longitude=-106.97)
613+
614+
sentinel_dataset = object()
615+
env._Environment__atm_type_file_to_function_map["forecast"][shortcut_name] = (
616+
lambda: sentinel_dataset
617+
)
618+
619+
captured = {}
620+
621+
def fake_process_forecast_reanalysis(file, dictionary):
622+
captured["file"] = file
623+
captured["dictionary"] = dictionary
624+
625+
monkeypatch.setattr(
626+
env, "process_forecast_reanalysis", fake_process_forecast_reanalysis
627+
)
628+
monkeypatch.setattr(env, "calculate_density_profile", lambda: None)
629+
monkeypatch.setattr(env, "calculate_speed_of_sound_profile", lambda: None)
630+
monkeypatch.setattr(env, "calculate_dynamic_viscosity", lambda: None)
631+
632+
# Act
633+
env.set_atmospheric_model(
634+
type="forecast",
635+
file=shortcut_name.lower(),
636+
dictionary=shortcut_name.lower(),
637+
)
638+
639+
# Assert
640+
expected_dictionary = env._Environment__weather_model_map.get(shortcut_name)
641+
assert captured["file"] is sentinel_dataset
642+
assert captured["dictionary"] == expected_dictionary
643+
assert env.atmospheric_model_file == shortcut_name
644+
assert env.atmospheric_model_dict == expected_dictionary
645+
646+
647+
def test_weather_model_mapping_get_is_case_insensitive():
648+
"""Ensure built-in mapping names are resolved regardless of casing."""
649+
mapping = WeatherModelMapping()
650+
assert mapping.get("aigfs") == mapping.get("AIGFS")
651+
assert mapping.get("ecmwf_v0") == mapping.get("ECMWF_v0")

0 commit comments

Comments
 (0)