diff --git a/tests/tap/classes/test_timeframe.py b/tests/tap/classes/test_timeframe.py index 37c7ba8..dd641d1 100644 --- a/tests/tap/classes/test_timeframe.py +++ b/tests/tap/classes/test_timeframe.py @@ -1,96 +1,134 @@ import pytest from src.tap.classes.timeframe import Time -@pytest.fixture(params=[(1.0, "second"), (100, "frame")]) -def time_obj(request): - # Arrange - data, unit = request.param - return Time(data, unit) +# Test cases as a constant for clarity and reusability +TEST_CASES = [ + (1.0, "second", 1.0, 100), + (100, "frame", 1.0, 100), +] + +INVALID_INIT_CASES = [ + (1.0, "invalid_unit"), + ("invalid_data", "second"), +] + +OPERATOR_CASES = [ + (Time(1.0, "second"), Time(1.0, "second"), 2.0), # Addition + (Time(2.0, "second"), Time(1.0, "second"), 1.0), # Subtraction + (Time(2.0, "second"), 2.0, 4.0), # Multiplication + (Time(2.0, "second"), 2.0, 1.0), # Division +] + +INVALID_OPERATOR_CASES = [ + (Time(3.11, "second"), 0.5), + (Time(2.0, "second"), 0.0), +] + +COMPARISON_CASES = [ + (Time(1.0, "second"), Time(2.0, "second"), True, True, False, False, False, True), + (Time(2.0, "second"), Time(1.0, "second"), False, False, True, True, False, True), + (Time(1.0, "second"), Time(1.0, "second"), False, True, False, True, True, False), + (Time(2.0, "second"), Time(2.0, "second"), False, True, False, True, True, False), +] + + +# Fixtures and tests +@pytest.fixture(params=TEST_CASES) +def valid_time_obj(request): + return Time(*request.param) + + +@pytest.mark.parametrize("data, unit, expected_second, expected_frame", TEST_CASES) +def test_time_init(data, unit, expected_second, expected_frame): + # Arrange & Act + time_obj = Time(data, unit) -def test_time_init(time_obj): # Assert - if time_obj.unit == "second": - assert time_obj.second == time_obj.data - assert time_obj.frame == time_obj.data * Time.FRAMES_PER_SECOND - elif time_obj.unit == "frame": - assert time_obj.second == time_obj.data / Time.FRAMES_PER_SECOND - assert time_obj.frame == time_obj.data - - -@pytest.mark.parametrize("data, unit", [ - (1.0, "invalid_unit"), - ("invalid_data", "second") -]) -def test_time_init_with_invalid_values(data, unit): - # Act & Assert + assert time_obj.second == expected_second + assert time_obj.frame == expected_frame + + +@pytest.mark.parametrize("data, unit", INVALID_INIT_CASES) +def test_time_init_with_invalid_inputs(data, unit): + # Arrange & Act & Assert with pytest.raises((ValueError, TypeError)): Time(data, unit) -@pytest.mark.parametrize("operator, result", [ - ("add", 2.0), - ("sub", 1.0) -]) -def test_time_arithmetic_operations(time_obj, operator, result): - # Arrange - time_obj2 = Time(1.0, "second") +@pytest.mark.parametrize("time_obj1, time_obj2, expected_result", OPERATOR_CASES) +def test_arithmetic_operations(time_obj1, time_obj2, expected_result): + # Arrange is done by parametrization + + # Act + result = ( + time_obj1 + time_obj2 if isinstance(time_obj2, Time) else time_obj1 * time_obj2 + ) + + # Assert + assert result.second == expected_result + + +@pytest.mark.parametrize("time_obj, scalar", INVALID_OPERATOR_CASES) +def test_arithmetic_operations_invalid(time_obj, scalar): + # Arrange is done by parametrization # Act & Assert - if operator == "add": - assert (time_obj + time_obj2).second == result - elif operator == "sub": - assert (time_obj - time_obj2).second == result - - -@pytest.mark.parametrize("scalar, result", [ - (2.0, 4.0), - (1.5, ValueError), - (0.0, ZeroDivisionError) -]) -def test_time_scalar_operations(time_obj, scalar, result): - # Act & Assert - if isinstance(result, type) and issubclass(result, Exception): - with pytest.raises(result): + with pytest.raises((ValueError, ZeroDivisionError)): + if scalar == 0.0: time_obj / scalar + else: time_obj * scalar - else: - assert (time_obj / scalar).second == result - assert (time_obj * scalar).second == 2 * result - - -@pytest.mark.parametrize("operator, time_obj2_data, result", [ - ("<", 2.0, True), - ("<=", 1.0, True), - (">", 1.0, False), - (">=", 2.0, False), - ("==", 1.0, True), - ("!=", 1.0, False) -]) -def test_time_comparison_operations(time_obj, operator, time_obj2_data, result): - # Arrange - time_obj2 = Time(time_obj2_data, "second") - # Act & Assert - assert eval(f"time_obj {operator} time_obj2") == result +@pytest.mark.parametrize( + "time_obj1, time_obj2, lt, le, gt, ge, eq, ne", COMPARISON_CASES +) +def test_comparison_operators(time_obj1, time_obj2, lt, le, gt, ge, eq, ne): + # Arrange is done by parametrization -def test_time_properties(time_obj): # Act & Assert - if time_obj.unit == "second": - assert time_obj.second == time_obj.data - elif time_obj.unit == "frame": - assert time_obj.frame == time_obj.data + assert (time_obj1 < time_obj2) == lt + assert (time_obj1 <= time_obj2) == le + assert (time_obj1 > time_obj2) == gt + assert (time_obj1 >= time_obj2) == ge + assert (time_obj1 == time_obj2) == eq + assert (time_obj1 != time_obj2) == ne -def test_time_str_repr(time_obj): - # Arrange - expected_result = f"Time(second={time_obj.second}, frame={time_obj.frame})" - - # Act - str_result = str(time_obj) - repr_result = repr(time_obj) +def test_second_property(valid_time_obj): + # Arrange & Act + result = valid_time_obj.second + + # Assert + assert result == valid_time_obj._second + + +def test_frame_property(valid_time_obj): + # Arrange & Act + result = valid_time_obj.frame + + # Assert + assert result == valid_time_obj._frame + + +def test_str_representation(valid_time_obj): + # Arrange & Act + result = str(valid_time_obj) + + # Assert + assert ( + result + == f"Time(second={valid_time_obj._second}, frame={valid_time_obj._frame})" + ) + + +def test_repr_representation(valid_time_obj): + # Arrange & Act + result = repr(valid_time_obj) # Assert - assert str_result == expected_result - assert repr_result == expected_result + assert ( + result + == f"Time(second={valid_time_obj._second}, frame={valid_time_obj._frame})" + )