diff --git a/.gitignore b/.gitignore index ed8cc5659..6b349a562 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,9 @@ instance/ # Sphinx documentation docs/_build/ +# WebServer extension +.iis + # PyBuilder .pybuilder/ target/ diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_environment.py b/tests/integration/test_environment.py similarity index 77% rename from tests/test_environment.py rename to tests/integration/test_environment.py index 0f23b2c11..9a6fce6dd 100644 --- a/tests/test_environment.py +++ b/tests/integration/test_environment.py @@ -1,88 +1,11 @@ -import datetime +import time +from datetime import datetime from unittest.mock import patch +import numpy.ma as ma import pytest - -@patch("matplotlib.pyplot.show") -def test_standard_atmosphere(mock_show, example_plain_env): - """Tests the standard atmosphere model in the environment object. - - Parameters - ---------- - mock_show : mock - Mock object to replace matplotlib.pyplot.show() method. - example_plain_env : rocketpy.Environment - Example environment object to be tested. - """ - example_plain_env.set_atmospheric_model(type="standard_atmosphere") - assert example_plain_env.info() == None - assert example_plain_env.all_info() == None - assert abs(example_plain_env.pressure(0) - 101325.0) < 1e-8 - assert abs(example_plain_env.barometric_height(101325.0)) < 1e-2 - assert example_plain_env.prints.print_earth_details() == None - - -@patch("matplotlib.pyplot.show") -def test_custom_atmosphere(mock_show, example_plain_env): - """Tests the custom atmosphere model in the environment object. - - Parameters - ---------- - mock_show : mock - Mock object to replace matplotlib.pyplot.show() method. - example_plain_env : rocketpy.Environment - Example environment object to be tested. - """ - example_plain_env.set_atmospheric_model( - type="custom_atmosphere", - pressure=None, - temperature=300, - wind_u=[(0, 5), (1000, 10)], - wind_v=[(0, -2), (500, 3), (1600, 2)], - ) - assert example_plain_env.all_info() == None - assert abs(example_plain_env.pressure(0) - 101325.0) < 1e-8 - assert abs(example_plain_env.barometric_height(101325.0)) < 1e-2 - assert abs(example_plain_env.wind_velocity_x(0) - 5) < 1e-8 - assert abs(example_plain_env.temperature(100) - 300) < 1e-8 - - -@patch("matplotlib.pyplot.show") -def test_wyoming_sounding_atmosphere(mock_show, example_plain_env): - """Tests the Wyoming sounding model in the environment object. - - Parameters - ---------- - mock_show : mock - Mock object to replace matplotlib.pyplot.show() method. - example_plain_env : rocketpy.Environment - Example environment object to be tested. - """ - # TODO:: this should be added to the set_atmospheric_model() method as a - # "file" option, instead of receiving the URL as a string. - URL = "http://weather.uwyo.edu/cgi-bin/sounding?region=samer&TYPE=TEXT%3ALIST&YEAR=2019&MONTH=02&FROM=0500&TO=0512&STNM=83779" - # give it at least 5 times to try to download the file - example_plain_env.set_atmospheric_model(type="wyoming_sounding", file=URL) - - assert example_plain_env.all_info() == None - assert abs(example_plain_env.pressure(0) - 93600.0) < 1e-8 - assert ( - abs(example_plain_env.barometric_height(example_plain_env.pressure(0)) - 722.0) - < 1e-8 - ) - assert abs(example_plain_env.wind_velocity_x(0) - -2.9005178894925043) < 1e-8 - assert abs(example_plain_env.temperature(100) - 291.75) < 1e-8 - - -@pytest.mark.skip(reason="legacy tests") -@pytest.mark.slow -@patch("matplotlib.pyplot.show") -def test_noaa_ruc_sounding_atmosphere(mock_show, example_plain_env): - URL = r"https://rucsoundings.noaa.gov/get_raobs.cgi?data_source=RAOB&latest=latest&start_year=2019&start_month_name=Feb&start_mday=5&start_hour=12&start_min=0&n_hrs=1.0&fcst_len=shortest&airport=83779&text=Ascii%20text%20%28GSD%20format%29&hydrometeors=false&start=latest" - example_plain_env.set_atmospheric_model(type="NOAARucSounding", file=URL) - assert example_plain_env.all_info() == None - assert example_plain_env.pressure(0) == 100000.0 +from rocketpy import Environment @pytest.mark.slow @@ -168,9 +91,8 @@ def test_gefs_atmosphere(mock_show, example_spaceport_env): @pytest.mark.skip(reason="legacy tests") # deprecated method @patch("matplotlib.pyplot.show") -def test_info_returns(mock_show, example_plain_env): - """Tests the all_info_returned() all_plot_info_returned() and methods of the - Environment class. +def test_custom_atmosphere(mock_show, example_plain_env): + """Tests the custom atmosphere model in the environment object. Parameters ---------- @@ -179,53 +101,72 @@ def test_info_returns(mock_show, example_plain_env): example_plain_env : rocketpy.Environment Example environment object to be tested. """ - returned_plots = example_plain_env.all_plot_info_returned() - returned_infos = example_plain_env.all_info_returned() - expected_info = { - "grav": example_plain_env.gravity, - "elevation": 0, - "model_type": "standard_atmosphere", - "model_type_max_expected_height": 80000, - "wind_speed": 0, - "wind_direction": 0, - "wind_heading": 0, - "surface_pressure": 1013.25, - "surface_temperature": 288.15, - "surface_air_density": 1.225000018124288, - "surface_speed_of_sound": 340.293988026089, - "lat": 0, - "lon": 0, - } - expected_plots_keys = [ - "grid", - "wind_speed", - "wind_direction", - "speed_of_sound", - "density", - "wind_vel_x", - "wind_vel_y", - "pressure", - "temperature", - ] - assert list(returned_infos.keys()) == list(expected_info.keys()) - assert list(returned_infos.values()) == list(expected_info.values()) - assert list(returned_plots.keys()) == expected_plots_keys + example_plain_env.set_atmospheric_model( + type="custom_atmosphere", + pressure=None, + temperature=300, + wind_u=[(0, 5), (1000, 10)], + wind_v=[(0, -2), (500, 3), (1600, 2)], + ) + assert example_plain_env.all_info() == None + assert abs(example_plain_env.pressure(0) - 101325.0) < 1e-8 + assert abs(example_plain_env.barometric_height(101325.0)) < 1e-2 + assert abs(example_plain_env.wind_velocity_x(0) - 5) < 1e-8 + assert abs(example_plain_env.temperature(100) - 300) < 1e-8 -@pytest.mark.slow @patch("matplotlib.pyplot.show") -def test_cmc_atmosphere(mock_show, example_spaceport_env): - """Tests the Ensemble model with the CMC file. +def test_standard_atmosphere(mock_show, example_plain_env): + """Tests the standard atmosphere model in the environment object. Parameters ---------- mock_show : mock Mock object to replace matplotlib.pyplot.show() method. - example_spaceport_env : rocketpy.Environment + example_plain_env : rocketpy.Environment Example environment object to be tested. """ - example_spaceport_env.set_atmospheric_model(type="Ensemble", file="CMC") - assert example_spaceport_env.all_info() == None + example_plain_env.set_atmospheric_model(type="standard_atmosphere") + assert example_plain_env.info() == None + assert example_plain_env.all_info() == None + assert abs(example_plain_env.pressure(0) - 101325.0) < 1e-8 + assert abs(example_plain_env.barometric_height(101325.0)) < 1e-2 + assert example_plain_env.prints.print_earth_details() == None + + +@patch("matplotlib.pyplot.show") +def test_wyoming_sounding_atmosphere(mock_show, example_plain_env): + """Asserts whether the Wyoming sounding model in the environment + object behaves as expected with respect to some attributes such + as pressure, barometric_height, wind_velocity and temperature. + + Parameters + ---------- + mock_show : mock + Mock object to replace matplotlib.pyplot.show() method. + example_plain_env : rocketpy.Environment + Example environment object to be tested. + """ + + # TODO:: this should be added to the set_atmospheric_model() method as a + # "file" option, instead of receiving the URL as a string. + URL = "http://weather.uwyo.edu/cgi-bin/sounding?region=samer&TYPE=TEXT%3ALIST&YEAR=2019&MONTH=02&FROM=0500&TO=0512&STNM=83779" + # give it at least 5 times to try to download the file + for i in range(5): + try: + example_plain_env.set_atmospheric_model(type="wyoming_sounding", file=URL) + break + except: + time.sleep(1) # wait 1 second before trying again + pass + assert example_plain_env.all_info() == None + assert abs(example_plain_env.pressure(0) - 93600.0) < 1e-8 + assert ( + abs(example_plain_env.barometric_height(example_plain_env.pressure(0)) - 722.0) + < 1e-8 + ) + assert abs(example_plain_env.wind_velocity_x(0) - -2.9005178894925043) < 1e-8 + assert abs(example_plain_env.temperature(100) - 291.75) < 1e-8 @pytest.mark.slow @@ -257,9 +198,27 @@ def test_hiresw_ensemble_atmosphere(mock_show, example_spaceport_env): date_string = f"{date_info[0]}{date_info[1]:02}{date_info[2]:02}" example_spaceport_env.set_date(date_info) + example_spaceport_env.set_atmospheric_model( type="Forecast", file=f"https://nomads.ncep.noaa.gov/dods/hiresw/hiresw{date_string}/hiresw_conusarw_12z", dictionary=HIRESW_dictionary, ) + + assert example_spaceport_env.all_info() == None + + +@pytest.mark.slow +@patch("matplotlib.pyplot.show") +def test_cmc_atmosphere(mock_show, example_spaceport_env): + """Tests the Ensemble model with the CMC file. + + Parameters + ---------- + mock_show : mock + Mock object to replace matplotlib.pyplot.show() method. + example_spaceport_env : rocketpy.Environment + Example environment object to be tested. + """ + example_spaceport_env.set_atmospheric_model(type="Ensemble", file="CMC") assert example_spaceport_env.all_info() == None diff --git a/tests/unit/test_environment.py b/tests/unit/test_environment.py index 8d676f426..58c0203cd 100644 --- a/tests/unit/test_environment.py +++ b/tests/unit/test_environment.py @@ -1,5 +1,6 @@ import json import os +from unittest.mock import patch import numpy as np import numpy.ma as ma @@ -9,35 +10,6 @@ from rocketpy import Environment -def test_date_naive_set_date_saves_utc_timezone_by_default( - example_plain_env, example_date_naive -): - """Tests environment.set_date sets timezone to UTC by default - - Parameters - ---------- - example_plain_env: rocketpy.Environment - example_date_naive: datetime.datetime - """ - example_plain_env.set_date(example_date_naive) - assert example_plain_env.datetime_date == pytz.utc.localize(example_date_naive) - - -def test_date_aware_set_date_saves_custom_timezone( - example_plain_env, example_date_naive -): - """Tests time zone is set accordingly in environment obj given a date_aware input - - Parameters - ---------- - example_plain_env: rocketpy.Environment - example_date_naive: datetime.datetime - """ - example_plain_env.set_date(example_date_naive, timezone="America/New_York") - example_date_aware = pytz.timezone("America/New_York").localize(example_date_naive) - assert example_plain_env.datetime_date == example_date_aware - - @pytest.mark.parametrize( "latitude, longitude", [(-21.960641, -47.482122), (0, 0), (21.960641, 47.482122)] ) @@ -59,12 +31,14 @@ def test_location_set_location_saves_location(latitude, longitude, example_plain @pytest.mark.parametrize("elevation", [(-200), (0), (200)]) def test_elevation_set_elevation_saves_elevation(elevation, example_plain_env): - """Tests elevation is set correctly in the environment obj. + """Tests the wether the 'set_elevation' method within the Environment class + sets the elevation correctly. Parameters ---------- example_plain_env : rocketpy.Environment """ + example_plain_env.set_elevation(elevation=elevation) assert example_plain_env.elevation == elevation @@ -97,75 +71,6 @@ def test_location_set_topographic_profile_computes_elevation( assert computed_elevation == theoretical_elevation -def test_environment_export_environment_exports_valid_environment_json( - example_spaceport_env, -): - """Tests the export_environment() method of the Environment class. - - Parameters - ---------- - example_spaceport_env : rocketpy.Environment - """ - # Check file creation - assert example_spaceport_env.export_environment(filename="environment") is None - with open("environment.json", "r") as json_file: - exported_env = json.load(json_file) - assert os.path.isfile("environment.json") - - # Check file content - assert exported_env["gravity"] == example_spaceport_env.gravity( - example_spaceport_env.elevation - ) - assert exported_env["date"] == [ - example_spaceport_env.datetime_date.year, - example_spaceport_env.datetime_date.month, - example_spaceport_env.datetime_date.day, - example_spaceport_env.datetime_date.hour, - ] - assert exported_env["latitude"] == example_spaceport_env.latitude - assert exported_env["longitude"] == example_spaceport_env.longitude - assert exported_env["elevation"] == example_spaceport_env.elevation - assert exported_env["datum"] == example_spaceport_env.datum - assert exported_env["timezone"] == example_spaceport_env.timezone - assert exported_env["max_expected_height"] == float( - example_spaceport_env.max_expected_height - ) - assert ( - exported_env["atmospheric_model_type"] - == example_spaceport_env.atmospheric_model_type - ) - assert exported_env["atmospheric_model_file"] == "" - assert exported_env["atmospheric_model_dict"] == "" - assert ( - exported_env["atmospheric_model_pressure_profile"] - == ma.getdata( - example_spaceport_env.pressure.get_source()(example_spaceport_env.height) - ).tolist() - ) - assert ( - exported_env["atmospheric_model_temperature_profile"] - == ma.getdata(example_spaceport_env.temperature.get_source()).tolist() - ) - assert ( - exported_env["atmospheric_model_wind_velocity_x_profile"] - == ma.getdata( - example_spaceport_env.wind_velocity_x.get_source()( - example_spaceport_env.height - ) - ).tolist() - ) - assert ( - exported_env["atmospheric_model_wind_velocity_y_profile"] - == ma.getdata( - example_spaceport_env.wind_velocity_y.get_source()( - example_spaceport_env.height - ) - ).tolist() - ) - - os.remove("environment.json") - - def test_geodesic_coordinate_geodesic_to_utm_converts_coordinate(): """Tests the conversion from geodesic to UTM coordinates.""" x, y, utm_zone, utm_letter, hemis, EW = Environment.geodesic_to_utm( @@ -182,8 +87,11 @@ def test_geodesic_coordinate_geodesic_to_utm_converts_coordinate(): assert EW == "W" -def test_utm_coordinate_utm_to_geodesic_converts_coordinate(): - """Tests the conversion from UTM to geodesic coordinates.""" +def test_utm_to_geodesic_converts_coordinates(): + """Tests the utm_to_geodesic method within the Environment + class and checks the conversion results from UTM to geodesic + coordinates. + """ lat, lon = Environment.utm_to_geodesic( x=315468.64, @@ -248,3 +156,146 @@ def test_decimal_degrees_to_arc_seconds_computes_correct_values( assert pytest.approx(computed_data[0], abs=1e-8) == theoretical_degree assert pytest.approx(computed_data[1], abs=1e-8) == theoretical_arc_minutes assert pytest.approx(computed_data[2], abs=1e-8) == theoretical_arc_seconds + + +@patch("matplotlib.pyplot.show") +def test_info_returns(mock_show, example_plain_env): + """Tests the all_info_returned() all_plot_info_returned() and methods of the + Environment class. + + Parameters + ---------- + mock_show : mock + Mock object to replace matplotlib.pyplot.show() method. + example_plain_env : rocketpy.Environment + Example environment object to be tested. + """ + returned_plots = example_plain_env.all_plot_info_returned() + returned_infos = example_plain_env.all_info_returned() + expected_info = { + "grav": example_plain_env.gravity, + "elevation": 0, + "model_type": "standard_atmosphere", + "model_type_max_expected_height": 80000, + "wind_speed": 0, + "wind_direction": 0, + "wind_heading": 0, + "surface_pressure": 1013.25, + "surface_temperature": 288.15, + "surface_air_density": 1.225000018124288, + "surface_speed_of_sound": 340.293988026089, + "lat": 0, + "lon": 0, + } + expected_plots_keys = [ + "grid", + "wind_speed", + "wind_direction", + "speed_of_sound", + "density", + "wind_vel_x", + "wind_vel_y", + "pressure", + "temperature", + ] + assert list(returned_infos.keys()) == list(expected_info.keys()) + assert list(returned_infos.values()) == list(expected_info.values()) + assert list(returned_plots.keys()) == expected_plots_keys + + +def test_date_naive_set_date_saves_utc_timezone_by_default( + example_plain_env, example_date_naive +): + """Tests environment.set_date sets timezone to UTC by default + + Parameters + ---------- + example_plain_env: rocketpy.Environment + example_date_naive: datetime.datetime + """ + example_plain_env.set_date(example_date_naive) + assert example_plain_env.datetime_date == pytz.utc.localize(example_date_naive) + + +def test_date_aware_set_date_saves_custom_timezone( + example_plain_env, example_date_naive +): + """Tests time zone is set accordingly in environment obj given a date_aware input + + Parameters + ---------- + example_plain_env: rocketpy.Environment + example_date_naive: datetime.datetime + """ + example_plain_env.set_date(example_date_naive, timezone="America/New_York") + example_date_aware = pytz.timezone("America/New_York").localize(example_date_naive) + assert example_plain_env.datetime_date == example_date_aware + + +def test_environment_export_environment_exports_valid_environment_json( + example_spaceport_env, +): + """Tests the export_environment() method of the Environment class. + + Parameters + ---------- + example_spaceport_env : rocketpy.Environment + """ + # Check file creation + assert example_spaceport_env.export_environment(filename="environment") is None + with open("environment.json", "r") as json_file: + exported_env = json.load(json_file) + assert os.path.isfile("environment.json") + + # Check file content + assert exported_env["gravity"] == example_spaceport_env.gravity( + example_spaceport_env.elevation + ) + assert exported_env["date"] == [ + example_spaceport_env.datetime_date.year, + example_spaceport_env.datetime_date.month, + example_spaceport_env.datetime_date.day, + example_spaceport_env.datetime_date.hour, + ] + assert exported_env["latitude"] == example_spaceport_env.latitude + assert exported_env["longitude"] == example_spaceport_env.longitude + assert exported_env["elevation"] == example_spaceport_env.elevation + assert exported_env["datum"] == example_spaceport_env.datum + assert exported_env["timezone"] == example_spaceport_env.timezone + assert exported_env["max_expected_height"] == float( + example_spaceport_env.max_expected_height + ) + assert ( + exported_env["atmospheric_model_type"] + == example_spaceport_env.atmospheric_model_type + ) + assert exported_env["atmospheric_model_file"] == "" + assert exported_env["atmospheric_model_dict"] == "" + assert ( + exported_env["atmospheric_model_pressure_profile"] + == ma.getdata( + example_spaceport_env.pressure.get_source()(example_spaceport_env.height) + ).tolist() + ) + assert ( + exported_env["atmospheric_model_temperature_profile"] + == ma.getdata(example_spaceport_env.temperature.get_source()).tolist() + ) + assert ( + exported_env["atmospheric_model_wind_velocity_x_profile"] + == ma.getdata( + example_spaceport_env.wind_velocity_x.get_source()( + example_spaceport_env.height + ) + ).tolist() + ) + assert ( + exported_env["atmospheric_model_wind_velocity_y_profile"] + == ma.getdata( + example_spaceport_env.wind_velocity_y.get_source()( + example_spaceport_env.height + ) + ).tolist() + ) + + os.remove("environment.json")