diff --git a/rocketpy/mathutils/function.py b/rocketpy/mathutils/function.py index e0b38381d..1552f9c4a 100644 --- a/rocketpy/mathutils/function.py +++ b/rocketpy/mathutils/function.py @@ -4,8 +4,8 @@ carefully as it may impact all the rest of the project. """ import warnings -from inspect import signature from collections.abc import Iterable +from inspect import signature from pathlib import Path import matplotlib.pyplot as plt diff --git a/tests/test_flight.py b/tests/test_flight.py index 1fafb7bcc..f658acba1 100644 --- a/tests/test_flight.py +++ b/tests/test_flight.py @@ -147,7 +147,7 @@ def test_initial_solution(mock_show, example_env, calisto_robust): def test_get_solution_at_time(flight_calisto): """Test the get_solution_at_time method of the Flight class. This test simply calls the method at the initial and final time and checks if the - returned values are correct. + returned values are correct. Also, checking for valid return instance. Parameters ---------- @@ -155,6 +155,11 @@ def test_get_solution_at_time(flight_calisto): Flight object to be tested. See the conftest.py file for more info regarding this pytest fixture. """ + assert isinstance(flight_calisto.get_solution_at_time(0), np.ndarray) + assert isinstance( + flight_calisto.get_solution_at_time(flight_calisto.t_final), np.ndarray + ) + assert np.allclose( flight_calisto.get_solution_at_time(0), np.array([0, 0, 0, 0, 0, 0, 0, 0.99904822, -0.04361939, 0, 0, 0, 0, 0]), @@ -576,7 +581,7 @@ def test_lat_lon_conversion_from_origin(mock_show, example_env, calisto_robust): ], ) def test_rail_length(calisto_robust, example_env, rail_length, out_of_rail_time): - """Test the rail length parameter of the Flight class. This test simply + """Tests the rail length parameter of the Flight class. This test simply simulate the flight using different rail lengths and checks if the expected out of rail altitude is achieved. Four different rail lengths are tested: 0.001, 1, 10, and 100000 meters. This provides a good test range. diff --git a/tests/test_function.py b/tests/test_function.py index 2e4265f1e..545790b6d 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -88,7 +88,7 @@ def test_plots(mock_show, func_from_csv): def test_interpolation_methods(linear_func): - """Test some of the interpolation methods of the Function class. Methods + """Tests some of the interpolation methods of the Function class. Methods not tested here are already being called in other tests. Parameters @@ -97,12 +97,17 @@ def test_interpolation_methods(linear_func): A Function object created from a list of values. """ # Test Akima + assert isinstance(linear_func.set_interpolation("akima"), Function) linear_func.set_interpolation("akima") + assert isinstance(linear_func.get_interpolation_method(), str) assert linear_func.get_interpolation_method() == "akima" assert np.isclose(linear_func.get_value(0), 0.0, atol=1e-6) # Test polynomial + + assert isinstance(linear_func.set_interpolation("polynomial"), Function) linear_func.set_interpolation("polynomial") + assert isinstance(linear_func.get_interpolation_method(), str) assert linear_func.get_interpolation_method() == "polynomial" assert np.isclose(linear_func.get_value(0), 0.0, atol=1e-6) @@ -122,12 +127,16 @@ def test_extrapolation_methods(linear_func): assert np.isclose(linear_func.get_value(-1), 0, atol=1e-6) # Test constant + assert isinstance(linear_func.set_extrapolation("constant"), Function) linear_func.set_extrapolation("constant") + assert isinstance(linear_func.get_extrapolation_method(), str) assert linear_func.get_extrapolation_method() == "constant" assert np.isclose(linear_func.get_value(-1), 0, atol=1e-6) # Test natural + assert isinstance(linear_func.set_extrapolation("natural"), Function) linear_func.set_extrapolation("natural") + assert isinstance(linear_func.get_extrapolation_method(), str) assert linear_func.get_extrapolation_method() == "natural" assert np.isclose(linear_func.get_value(-1), -1, atol=1e-6) @@ -143,6 +152,7 @@ def test_integral_linear_interpolation(linearly_interpolated_func, a, b): A Function object created from a list of values. """ # Test integral + assert isinstance(linearly_interpolated_func.integral(a, b, numerical=True), float) assert np.isclose( linearly_interpolated_func.integral(a, b, numerical=False), linearly_interpolated_func.integral(a, b, numerical=True), @@ -175,6 +185,75 @@ def test_integral_spline_interpolation(request, func, a, b): ) +def test_differentiate(): + """Tests the differentiation method of the Function class. + Both with respect to return instances and expected behaviour. + """ + func = Function(1) + assert isinstance(func.differentiate(0), float) + assert np.isclose(func.differentiate(5), 0) + + func_x = Function(lambda x: x) + assert isinstance(func_x.differentiate(0), float) + assert np.isclose(func_x.differentiate(0), 1) + + f_square = Function(lambda x: x**2) + assert isinstance(f_square.differentiate(1), float) + assert np.isclose(f_square.differentiate(1), 2) + + +def test_get_value(): + """Tests the get_value method of the Function class. + Both with respect to return instances and expected behaviour. + """ + func = Function(lambda x: 2 * x) + assert isinstance(func.get_value(1), int or float) + + +def test_identity_function(): + """Tests the identity_function method of the Function class. + Both with respect to return instances and expected behaviour. + """ + + func = Function(lambda x: x**2) + assert isinstance(func.identity_function(), Function) + + +def test_derivative_function(): + """Tests the derivative_function method of the Function class. + Both with respect to return instances and expected behaviour. + """ + square = Function(lambda x: x**2) + assert isinstance(square.derivative_function(), Function) + + +def test_integral(): + """Tests the integral method of the Function class. + Both with respect to return instances and expected behaviour. + """ + + zero_func = Function(0) + assert isinstance(zero_func.integral(2, 4, numerical=True), float) + assert zero_func.integral(2, 4, numerical=True) == 0 + + square = Function(lambda x: x**2) + assert isinstance + assert square.integral(2, 4, numerical=True) == -square.integral( + 4, 2, numerical=True + ) + assert square.integral(2, 4, numerical=False) == -square.integral( + 4, 2, numerical=False + ) + + +def test_integral_function(): + """Tests the integral_function method of the Function class. + Both with respect to return instances and expected behaviour. + """ + zero_func = Function(0) + assert isinstance(zero_func, Function) + + @pytest.mark.parametrize("a", [-1, 0, 1]) @pytest.mark.parametrize("b", [-1, 0, 1]) def test_multivariable_dataset(a, b): diff --git a/tests/test_rocket.py b/tests/test_rocket.py index 33e96a6ae..160ab9aa4 100644 --- a/tests/test_rocket.py +++ b/tests/test_rocket.py @@ -3,7 +3,8 @@ import numpy as np import pytest -from rocketpy import NoseCone, Rocket, SolidMotor +from rocketpy import NoseCone, Rocket, SolidMotor, Function +from rocketpy.motors.motor import Motor, EmptyMotor @patch("matplotlib.pyplot.show") @@ -489,6 +490,27 @@ def test_add_cp_eccentricity_assert_properties_set(calisto): assert calisto.cp_eccentricity_y == 5 +def test_add_motor(calisto_motorless, cesaroni_m1670): + """Tests the add_motor method of the Rocket class. + Both with respect to return instances and expected behaviour. + Parameters + ---------- + calisto_motorless : Rocket instance + A predefined instance of a Rocket without a motor, used as a base for testing. + cesaroni_m1670 : rocketpy.SolidMotor + Cesaroni M1670 motor + """ + + assert isinstance(calisto_motorless.motor, EmptyMotor) + center_of_mass_motorless = calisto_motorless.center_of_mass + calisto_motorless.add_motor(cesaroni_m1670, 0) + + assert isinstance(calisto_motorless.motor, Motor) + center_of_mass_with_motor = calisto_motorless.center_of_mass + + assert center_of_mass_motorless is not center_of_mass_with_motor + + def test_set_rail_button(calisto): rail_buttons = calisto.set_rail_buttons(0.2, -0.5, 30) # assert buttons_distance @@ -509,3 +531,26 @@ def test_set_rail_button(calisto): assert calisto.rail_buttons[0].component.buttons_distance + calisto.rail_buttons[ 0 ].position == pytest.approx(0.2, 1e-12) + + +def test_evaluate_total_mass(calisto_motorless): + """Tests the evaluate_total_mass method of the Rocket class. + Both with respect to return instances and expected behaviour. + + Parameters + ---------- + calisto_motorless : Rocket instance + A predefined instance of a Rocket without a motor, used as a base for testing. + """ + assert isinstance(calisto_motorless.evaluate_total_mass(), Function) + + +def test_evaluate_center_of_mass(calisto): + """Tests the evaluate_center_of_mass method of the Rocket class. + Both with respect to return instances and expected behaviour. + Parameters + ---------- + calisto : Rocket instance + A predefined instance of the calisto Rocket with a motor, used as a base for testing. + """ + assert isinstance(calisto.evaluate_center_of_mass(), Function)