From f7f68ee121794231520b6bbdf86caa72d2c9c601 Mon Sep 17 00:00:00 2001 From: GabrielBarberini Date: Wed, 6 Mar 2024 19:07:56 -0300 Subject: [PATCH] TST: refactors environment.set_date test TST: refactors tests/unit/test_environment TST: refactors environment_fixtures DOC: fix doc typo in decimal_degrees_to_arc_seconds --- rocketpy/environment/environment.py | 2 +- .../environment/environment_fixtures.py | 45 +++-- tests/unit/test_environment.py | 173 +++++++++--------- 3 files changed, 108 insertions(+), 112 deletions(-) diff --git a/rocketpy/environment/environment.py b/rocketpy/environment/environment.py index 8b8d0498a..00a87dbc9 100644 --- a/rocketpy/environment/environment.py +++ b/rocketpy/environment/environment.py @@ -3696,7 +3696,7 @@ def decimal_degrees_to_arc_seconds(angle): ------- degrees : float The degrees. - arc_minutes : float + arc_minutes : int The arc minutes. 1 arc-minute = (1/60)*degree arc_seconds : float The arc Seconds. 1 arc-second = (1/3600)*degree diff --git a/tests/fixtures/environment/environment_fixtures.py b/tests/fixtures/environment/environment_fixtures.py index 54bc8bcce..2b787a1f3 100644 --- a/tests/fixtures/environment/environment_fixtures.py +++ b/tests/fixtures/environment/environment_fixtures.py @@ -1,58 +1,57 @@ -import datetime - import pytest - +import os +from datetime import datetime, timedelta from rocketpy import Environment, EnvironmentAnalysis @pytest.fixture -def example_env(): - """Create a simple object of the Environment class to be used in the tests. - This allows to avoid repeating the same code in all tests. The environment - set here is the simplest possible, with no parameters set. +def example_plain_env(): + """Simple object of the Environment class to be used in the tests. Returns ------- rocketpy.Environment - The simplest object of the Environment class """ return Environment() @pytest.fixture -def example_env_robust(): - """Create an object of the Environment class to be used in the tests. This - allows to avoid repeating the same code in all tests. The environment set - here is a bit more complex than the one in the example_env fixture. This - time the latitude, longitude and elevation are set, as well as the datum and - the date. The location refers to the Spaceport America Cup launch site, - while the date is set to tomorrow at noon. +def example_date_naive(): + """Naive tomorrow date + + Returns + ------- + datetime.datetime + """ + return datetime.now() + timedelta(days=1) + + +@pytest.fixture +def example_spaceport_env(example_date_naive): + """Environment class with location set to Spaceport America Cup launch site Returns ------- rocketpy.Environment - An object of the Environment class """ - env = Environment( + spaceport_env = Environment( latitude=32.990254, longitude=-106.974998, elevation=1400, datum="WGS84", ) - tomorrow = datetime.date.today() + datetime.timedelta(days=1) - env.set_date((tomorrow.year, tomorrow.month, tomorrow.day, 12)) - return env + spaceport_env.set_date(example_date_naive) + yield spaceport_env + os.remove("environment.json") @pytest.fixture def env_analysis(): - """Create a simple object of the Environment Analysis class to be used in - the tests. This allows to avoid repeating the same code in all tests. + """Environment Analysis class with hardcoded parameters Returns ------- EnvironmentAnalysis - A simple object of the Environment Analysis class """ env_analysis = EnvironmentAnalysis( start_date=datetime.datetime(2019, 10, 23), diff --git a/tests/unit/test_environment.py b/tests/unit/test_environment.py index 463238276..417c0ce61 100644 --- a/tests/unit/test_environment.py +++ b/tests/unit/test_environment.py @@ -1,4 +1,3 @@ -import datetime import os import numpy as np @@ -8,109 +7,105 @@ from rocketpy import Environment -def test_env_set_date(example_env): - """Test that the date is set correctly in the environment object. This - basically takes a date and time and converts it to a datetime object, then - set the date to the example environment object. The test checks if the - datetime object is the same as the one in the example environment object. +def test_date_naive_set_date_saves_utc_timezone_by_default( + example_plain_env, example_date_naive +): + """Tests time zone is set to UTC by default in environment obj given a date_naive input Parameters ---------- - example_env : rocketpy.Environment - Example environment object to be tested. + example_plain_env: rocketpy.Environment + example_date_naive: datetime.datetime """ - tomorrow = datetime.date.today() + datetime.timedelta(days=1) - example_env.set_date((tomorrow.year, tomorrow.month, tomorrow.day, 12)) - assert example_env.datetime_date == datetime.datetime( - tomorrow.year, tomorrow.month, tomorrow.day, 12, tzinfo=pytz.utc - ) + example_plain_env.set_date(example_date_naive) + assert example_plain_env.datetime_date == pytz.utc.localize(example_date_naive) -def test_env_set_date_time_zone(example_env): - """Test that the time zone is set correctly in the environment object +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_env : rocketpy.Environment - Example environment object to be tested. + example_plain_env: rocketpy.Environment + example_date_naive: datetime.datetime """ - tomorrow = datetime.date.today() + datetime.timedelta(days=1) - example_env.set_date( - (tomorrow.year, tomorrow.month, tomorrow.day, 12), timezone="America/New_York" - ) - date_naive = datetime.datetime(tomorrow.year, tomorrow.month, tomorrow.day, 12) - timezone = pytz.timezone("America/New_York") - date_aware_local_date = timezone.localize(date_naive) - date_aware_utc = date_aware_local_date.astimezone(pytz.UTC) - assert example_env.datetime_date == date_aware_utc + 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_env_set_location(example_env): - """Test that the location is set correctly in the environment object. This - one basically set the location using the set_location() method and then - checks if the latitude and longitude are the same as the ones in the - example environment object. +@pytest.mark.parametrize( + "latitude, longitude", [(-21.960641, -47.482122), (0, 0), (21.960641, 47.482122)] +) +def test_location_set_location_saves_location(latitude, longitude, example_plain_env): + """Tests location is saved correctly in the environment obj. Parameters ---------- - example_env : rocketpy.Environment - Example environment object to be tested. + example_plain_env : rocketpy.Environment + latitude: float + The latitude in decimal degrees. + longitude: float + The longitude in decimal degrees. """ - example_env.set_location(-21.960641, -47.482122) - assert example_env.latitude == -21.960641 - assert example_env.longitude == -47.482122 + example_plain_env.set_location(latitude, longitude) + assert example_plain_env.latitude == latitude + assert example_plain_env.longitude == longitude -def test_set_elevation(example_env): - """Tests if the elevation is set correctly in the environment object. This - one basically set the elevation using the set_elevation() method and then - checks if the elevation is the same as the one in the example environment - object. +@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. Parameters ---------- - example_env : rocketpy.Environment - Example environment object to be tested. + example_plain_env : rocketpy.Environment """ - example_env.set_elevation(elevation=200) - assert example_env.elevation == 200 + example_plain_env.set_elevation(elevation=elevation) + assert example_plain_env.elevation == elevation -def test_set_topographic_profile(example_env): - """Tests the topographic profile in the environment object. +@pytest.mark.parametrize( + "latitude, longitude, theoretical_elevation", [(46.90479, 8.07575, 1565)] +) +def test_location_set_topographic_profile_computes_elevation( + latitude, longitude, theoretical_elevation, example_plain_env +): + """Tests elevation computation given topographic profile in the environment obj. Parameters ---------- - example_env : rocketpy.Environment - Example environment object to be tested. + example_plain_env : rocketpy.Environment + latitude: float + The latitude in decimal degrees. + longitude: float + The longitude in decimal degrees. """ - example_env.set_location(46.90479, 8.07575) - example_env.set_topographic_profile( + example_plain_env.set_topographic_profile( type="NASADEM_HGT", file="data/sites/switzerland/NASADEM_NC_n46e008.nc", dictionary="netCDF4", ) - assert ( - example_env.get_elevation_from_topographic_profile( - example_env.latitude, example_env.longitude - ) - == 1565 + computed_elevation = example_plain_env.get_elevation_from_topographic_profile( + latitude, longitude ) + assert computed_elevation == theoretical_elevation -def test_export_environment(example_env_robust): +def test_environment_export_environment_exports_environment_json(example_spaceport_env): """Tests the export_environment() method of the Environment class. Parameters ---------- - example_env_robust : rocketpy.Environment - Example environment object to be tested. + example_spaceport_env : rocketpy.Environment """ - assert example_env_robust.export_environment(filename="environment") == None - os.remove("environment.json") + assert example_spaceport_env.export_environment(filename="environment") == None + assert os.path.isfile("environment.json") -def test_geodesic_to_utm(): +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( lat=32.990254, @@ -126,7 +121,7 @@ def test_geodesic_to_utm(): assert EW == "W" -def test_utm_to_geodesic(): +def test_utm_coordinate_utm_to_geodesic_converts_coordinate(): """Tests the conversion from UTM to geodesic coordinates.""" lat, lon = Environment.utm_to_geodesic( @@ -142,51 +137,53 @@ def test_utm_to_geodesic(): @pytest.mark.parametrize( - "lat, radius", [(0, 6378137.0), (90, 6356752.31424518), (-90, 6356752.31424518)] + "latitude, theoretical_radius", + [(0, 6378137.0), (90, 6356752.31424518), (-90, 6356752.31424518)], ) -def test_earth_radius_calculation(lat, radius): - """Tests if the earth radius calculation is correct. It takes 3 different - latitudes and their expected results and compares them with the results - from the method. +def test_latitude_calculate_earth_radius_computes_radius(latitude, theoretical_radius): + """Tests earth radius calculation. Parameters ---------- - lat : float + latitude : float The latitude in decimal degrees. - radius : float + theoretical_radius : float The expected radius in meters at the given latitude. """ semi_major_axis = 6378137.0 # WGS84 flattening = 1 / 298.257223563 # WGS84 - res = Environment.calculate_earth_radius(lat, semi_major_axis, flattening) - assert pytest.approx(res, abs=1e-8) == radius + computed_radius = Environment.calculate_earth_radius( + latitude, semi_major_axis, flattening + ) + assert pytest.approx(computed_radius, abs=1e-8) == theoretical_radius @pytest.mark.parametrize( - "angle, deg, arc_min, arc_sec", + "angle, theoretical_degree, theoretical_arc_minutes, theoretical_arc_seconds", [ (-106.974998, -106.0, 58, 29.9928), - (32.990254, 32, 59.0, 24.9144), + (32.990254, 32, 59, 24.9144), (90.0, 90, 0, 0), ], ) -def test_decimal_degrees_to_arc_seconds(angle, deg, arc_min, arc_sec): - """Tests if the conversion from decimal degrees to arc seconds is correct. - It takes 3 different angles and their expected results and compares them - with the results from the method. +def test_decimal_degrees_to_arc_seconds_computes_correct_values( + angle, theoretical_degree, theoretical_arc_minutes, theoretical_arc_seconds +): + """Tests the conversion from decimal degrees to degrees, arc minutes, and arc seconds. Parameters ---------- angle : float Angle in decimal degrees. - deg : int - Expected degrees. - arc_min : int - Expected arc minutes. - arc_sec : float - Expected arc seconds. + theoretical_degree : int + Expected computed integer degrees. + theoretical_arc_minutes : int + Expected computed arc minutes. + theoretical_arc_seconds : float + Expected computed arc seconds. """ - res = Environment.decimal_degrees_to_arc_seconds(angle) - assert pytest.approx(res[0], abs=1e-8) == deg - assert pytest.approx(res[1], abs=1e-8) == arc_min - assert pytest.approx(res[2], abs=1e-8) == arc_sec + computed_data = Environment.decimal_degrees_to_arc_seconds(angle) + + 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