Skip to content

Commit

Permalink
Merge pull request #556 from RocketPy-Team/mnt/refactoring-fixtures
Browse files Browse the repository at this point in the history
TST: Splitting conftest.py into several smaller files.
  • Loading branch information
lucasfourier authored Feb 19, 2024
2 parents 9da1542 + 79aa3b6 commit e7b17de
Show file tree
Hide file tree
Showing 24 changed files with 1,560 additions and 1,270 deletions.
1,284 changes: 14 additions & 1,270 deletions tests/conftest.py

Large diffs are not rendered by default.

Empty file added tests/fixtures/__init__.py
Empty file.
Empty file.
73 changes: 73 additions & 0 deletions tests/fixtures/environment/environment_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import datetime

import pytest

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.
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.
Returns
-------
rocketpy.Environment
An object of the Environment class
"""
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


@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.
Returns
-------
EnvironmentAnalysis
A simple object of the Environment Analysis class
"""
env_analysis = EnvironmentAnalysis(
start_date=datetime.datetime(2019, 10, 23),
end_date=datetime.datetime(2021, 10, 23),
latitude=39.3897,
longitude=-8.28896388889,
start_hour=6,
end_hour=18,
surface_data_file="./data/weather/EuroC_single_level_reanalysis_2002_2021.nc",
pressure_level_data_file="./data/weather/EuroC_pressure_levels_reanalysis_2001-2021.nc",
timezone=None,
unit_system="metric",
forecast_date=None,
forecast_args=None,
max_expected_altitude=None,
)

return env_analysis
Empty file.
160 changes: 160 additions & 0 deletions tests/fixtures/flight/flight_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import pytest

from rocketpy import Flight


@pytest.fixture
def flight_calisto(calisto, example_env): # old name: flight
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
without the aerodynamic surfaces and parachutes. The environment is the
simplest possible, with no parameters set.
Parameters
----------
calisto : rocketpy.Rocket
An object of the Rocket class. This is a pytest fixture too.
example_env : rocketpy.Environment
An object of the Environment class. This is a pytest fixture too.
Returns
-------
rocketpy.Flight
A rocketpy.Flight object of the Calisto rocket in the simplest possible
conditions.
"""
return Flight(
environment=example_env,
rocket=calisto,
rail_length=5.2,
inclination=85,
heading=0,
terminate_on_apogee=False,
)


@pytest.fixture
def flight_calisto_nose_to_tail(calisto_nose_to_tail, example_env):
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
with "nose_to_tail" coordinate system orientation, just as described in the
calisto_nose_to_tail fixture.
Parameters
----------
calisto_nose_to_tail : rocketpy.Rocket
An object of the Rocket class. This is a pytest fixture too.
example_env : rocketpy.Environment
An object of the Environment class. This is a pytest fixture too.
Returns
-------
rocketpy.Flight
The Calisto rocket with the coordinate system orientation set to
"nose_to_tail".
"""
return Flight(
environment=example_env,
rocket=calisto_nose_to_tail,
rail_length=5.2,
inclination=85,
heading=0,
terminate_on_apogee=False,
)


@pytest.fixture
def flight_calisto_robust(calisto_robust, example_env_robust):
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
with the aerodynamic surfaces and parachutes. The environment is a bit more
complex than the one in the flight_calisto 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.
Parameters
----------
calisto_robust : rocketpy.Rocket
An object of the Rocket class. This is a pytest fixture too.
example_env_robust : rocketpy.Environment
An object of the Environment class. This is a pytest fixture too.
Returns
-------
rocketpy.Flight
A rocketpy.Flight object of the Calisto rocket in a more complex
condition.
"""
return Flight(
environment=example_env_robust,
rocket=calisto_robust,
rail_length=5.2,
inclination=85,
heading=0,
terminate_on_apogee=False,
)


@pytest.fixture
def flight_calisto_custom_wind(calisto_robust, example_env_robust):
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
with the aerodynamic surfaces and parachutes. The environment is a bit more
complex than the one in the flight_calisto_robust fixture. Now the wind is
set to 5m/s (x direction) and 2m/s (y direction), constant with altitude.
Parameters
----------
calisto_robust : rocketpy.Rocket
An object of the Rocket class. This is a pytest fixture too.
example_env_robust : rocketpy.Environment
An object of the Environment class. This is a pytest fixture too.
Returns
-------
rocketpy.Flight
"""
env = example_env_robust
env.set_atmospheric_model(
type="custom_atmosphere",
temperature=300,
wind_u=[(0, 5), (4000, 5)],
wind_v=[(0, 2), (4000, 2)],
)
return Flight(
environment=env,
rocket=calisto_robust,
rail_length=5.2,
inclination=85,
heading=0,
terminate_on_apogee=False,
)


@pytest.fixture
def flight_calisto_air_brakes(calisto_air_brakes_clamp_on, example_env):
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
with the aerodynamic surfaces and air brakes. The environment is the
simplest possible, with no parameters set. The air brakes are set to clamp
the deployment level.
Parameters
----------
calisto_air_brakes_clamp_on : rocketpy.Rocket
An object of the Rocket class.
example_env : rocketpy.Environment
An object of the Environment class.
Returns
-------
rocketpy.Flight
A rocketpy.Flight object of the Calisto rocket in a more complex
condition.
"""
return Flight(
rocket=calisto_air_brakes_clamp_on,
environment=example_env,
rail_length=5.2,
inclination=85,
heading=0,
time_overshoot=False,
terminate_on_apogee=True,
)
Empty file.
140 changes: 140 additions & 0 deletions tests/fixtures/function/function_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import pytest

from rocketpy import Function


@pytest.fixture
def linear_func():
"""Create a linear function based on a list of points. The function
represents y = x and may be used on different tests.
Returns
-------
Function
A linear function representing y = x.
"""
return Function(
[[0, 0], [1, 1], [2, 2], [3, 3]],
)


@pytest.fixture
def linearly_interpolated_func():
"""Create a linearly interpolated function based on a list of points.
Returns
-------
Function
Linearly interpolated Function, with constant extrapolation
"""
return Function(
[[0, 0], [1, 7], [2, -3], [3, -1], [4, 3]],
interpolation="linear",
extrapolation="constant",
)


@pytest.fixture
def spline_interpolated_func():
"""Create a spline interpolated function based on a list of points.
Returns
-------
Function
Spline interpolated, with natural extrapolation
"""
return Function(
[[0, 0], [1, 7], [2, -3], [3, -1], [4, 3]],
interpolation="spline",
extrapolation="natural",
)


@pytest.fixture
def func_from_csv():
"""Create a function based on a csv file. The csv file contains the
coordinates of the E473 airfoil at 10e6 degrees, but anything else could be
used here as long as it is a csv file.
Returns
-------
rocketpy.Function
A function based on a csv file.
"""
func = Function(
source="tests/fixtures/airfoils/e473-10e6-degrees.csv",
)
return func


@pytest.fixture
def func_2d_from_csv():
"""Create a 2d function based on a csv file.
Returns
-------
rocketpy.Function
A function based on a csv file.
"""
# Do not define any of the optional parameters so that the tests can check
# if the defaults are being used correctly.
func = Function(
source="tests/fixtures/function/2d.csv",
)
return func


## Controller
@pytest.fixture
def controller_function():
"""Create a controller function that updates the air brakes deployment level
based on the altitude and vertical velocity of the rocket. This is the same
controller function that is used in the air brakes example in the
documentation.
Returns
-------
function
A controller function
"""

def controller_function(
time, sampling_rate, state, state_history, observed_variables, air_brakes
):
z = state[2]
vz = state[5]
previous_vz = state_history[-1][5]
if time < 3.9:
return None
if z < 1500:
air_brakes.deployment_level = 0
else:
new_deployment_level = (
air_brakes.deployment_level + 0.1 * vz + 0.01 * previous_vz**2
)
if new_deployment_level > air_brakes.deployment_level + 0.2 / sampling_rate:
new_deployment_level = air_brakes.deployment_level + 0.2 / sampling_rate
elif (
new_deployment_level < air_brakes.deployment_level - 0.2 / sampling_rate
):
new_deployment_level = air_brakes.deployment_level - 0.2 / sampling_rate
else:
new_deployment_level = air_brakes.deployment_level
air_brakes.deployment_level = new_deployment_level

return controller_function


@pytest.fixture
def lambda_quad_func():
"""Create a lambda function based on a string.
Returns
-------
Function
A lambda function based on a string.
"""
func = lambda x: x**2
return Function(
source=func,
)
Empty file.
Loading

0 comments on commit e7b17de

Please sign in to comment.