diff --git a/src/safeds/data/tabular/transformation/_imputer.py b/src/safeds/data/tabular/transformation/_imputer.py index 7f08114b1..f8bd25439 100644 --- a/src/safeds/data/tabular/transformation/_imputer.py +++ b/src/safeds/data/tabular/transformation/_imputer.py @@ -47,11 +47,11 @@ class Strategy(ABC): @abstractmethod def __eq__(self, other: object) -> bool: - pass + pass # pragma: no cover @abstractmethod def __hash__(self) -> int: - pass + pass # pragma: no cover @abstractmethod def _apply(self, imputer: sk_SimpleImputer) -> None: @@ -74,22 +74,22 @@ def Constant(value: Any) -> Imputer.Strategy: # noqa: N802 value: The value to replace missing values. """ - return _Constant(value) + return _Constant(value) # pragma: no cover @staticmethod def Mean() -> Imputer.Strategy: # noqa: N802 """Replace missing values with the mean of each column.""" - return _Mean() + return _Mean() # pragma: no cover @staticmethod def Median() -> Imputer.Strategy: # noqa: N802 """Replace missing values with the median of each column.""" - return _Median() + return _Median() # pragma: no cover @staticmethod def Mode() -> Imputer.Strategy: # noqa: N802 """Replace missing values with the mode of each column.""" - return _Mode() + return _Mode() # pragma: no cover def __init__(self, strategy: Imputer.Strategy, *, value_to_replace: float | str | None = None): if value_to_replace is None: diff --git a/tests/safeds/data/tabular/transformation/test_imputer.py b/tests/safeds/data/tabular/transformation/test_imputer.py index 53e61839b..82ef5254f 100644 --- a/tests/safeds/data/tabular/transformation/test_imputer.py +++ b/tests/safeds/data/tabular/transformation/test_imputer.py @@ -23,7 +23,101 @@ def strategies() -> list[Imputer.Strategy]: return [Imputer.Strategy.Constant(2), Imputer.Strategy.Mean(), Imputer.Strategy.Median(), Imputer.Strategy.Mode()] -class TestStrategy: +class TestStrategyClass: + def test_should_be_able_to_get_value_of_constant_strategy(self) -> None: + assert Imputer.Strategy.Constant(1).value == 1 # ignore: type[attr-defined] + + @pytest.mark.parametrize( + ("strategy", "type_", "expected"), + [ + (Imputer.Strategy.Constant(0), Imputer.Strategy.Constant, True), + (Imputer.Strategy.Mean(), Imputer.Strategy.Mean, True), + (Imputer.Strategy.Median(), Imputer.Strategy.Median, True), + (Imputer.Strategy.Mode(), Imputer.Strategy.Mode, True), + (Imputer.Strategy.Mode(), Imputer.Strategy.Mean, False), + ], + ) + def test_should_be_able_to_use_strategy_in_isinstance( + self, + strategy: Imputer.Strategy, + type_: type, + expected: bool, + ) -> None: + assert isinstance(strategy, type_) == expected + + class TestEq: + @pytest.mark.parametrize( + ("strategy1", "strategy2"), + ([(x, y) for x in strategies() for y in strategies() if x.__class__ == y.__class__]), + ids=lambda x: x.__class__.__name__, + ) + def test_equal_strategy( + self, + strategy1: Imputer.Strategy, + strategy2: Imputer.Strategy, + ) -> None: + assert strategy1 == strategy2 + + @pytest.mark.parametrize( + "strategy", + ([x for x in strategies() if x.__class__]), + ids=lambda x: x.__class__.__name__, + ) + def test_equal_identity_strategy( + self, + strategy: Imputer.Strategy, + ) -> None: + assert strategy == strategy # noqa: PLR0124 + + @pytest.mark.parametrize( + ("strategy1", "strategy2"), + ([(x, y) for x in strategies() for y in strategies() if x.__class__ != y.__class__]), + ids=lambda x: x.__class__.__name__, + ) + def test_unequal_strategy( + self, + strategy1: Imputer.Strategy, + strategy2: Imputer.Strategy, + ) -> None: + assert strategy1 != strategy2 + + class TestHash: + @pytest.mark.parametrize( + ("strategy1", "strategy2"), + ([(x, y) for x in strategies() for y in strategies() if x.__class__ == y.__class__]), + ids=lambda x: x.__class__.__name__, + ) + def test_should_return_same_hash_for_equal_strategy( + self, + strategy1: Imputer.Strategy, + strategy2: Imputer.Strategy, + ) -> None: + assert hash(strategy1) == hash(strategy2) + + @pytest.mark.parametrize( + ("strategy1", "strategy2"), + ([(x, y) for x in strategies() for y in strategies() if x.__class__ != y.__class__]), + ids=lambda x: x.__class__.__name__, + ) + def test_should_return_different_hash_for_unequal_strategy( + self, + strategy1: Imputer.Strategy, + strategy2: Imputer.Strategy, + ) -> None: + assert hash(strategy1) != hash(strategy2) + + class TestSizeof: + @pytest.mark.parametrize( + "strategy", + ([Imputer.Strategy.Constant(1)]), + ids=lambda x: x.__class__.__name__, + ) + def test_sizeof_strategy( + self, + strategy: Imputer.Strategy, + ) -> None: + assert sys.getsizeof(strategy) > sys.getsizeof(object()) + class TestStr: @pytest.mark.parametrize( ("strategy", "expected"), @@ -33,12 +127,31 @@ class TestStr: (Imputer.Strategy.Median(), "Median"), (Imputer.Strategy.Mode(), "Mode"), ], - ids=["Constant", "Mean", "Median", "Mode"], + ids=lambda x: x.__class__.__name__, ) def test_should_return_correct_string_representation(self, strategy: Imputer.Strategy, expected: str) -> None: assert str(strategy) == expected +class TestStrategyProperty: + @pytest.mark.parametrize( + "strategy", + strategies(), + ids=lambda x: x.__class__.__name__, + ) + def test_should_return_correct_strategy(self, strategy: Imputer.Strategy) -> None: + assert Imputer(strategy).strategy == strategy + + +class TestValueToReplaceProperty: + @pytest.mark.parametrize( + "value_to_replace", + [0], + ) + def test_should_return_correct_value_to_replace(self, value_to_replace: float | str | None) -> None: + assert Imputer(Imputer.Strategy.Mode(), value_to_replace=value_to_replace).value_to_replace == value_to_replace + + class TestFit: @pytest.mark.parametrize("strategy", strategies(), ids=lambda x: x.__class__.__name__) def test_should_raise_if_column_not_found(self, strategy: Imputer.Strategy) -> None: @@ -385,80 +498,3 @@ def test_get_names_of_removed_columns(self, strategy: Imputer.Strategy) -> None: ) transformer = transformer.fit(table, None) assert transformer.get_names_of_removed_columns() == [] - - -class TestHash: - @pytest.mark.parametrize( - ("strategy1", "strategy2"), - ([(x, y) for x in strategies() for y in strategies() if x.__class__ == y.__class__]), - ids=lambda x: x.__class__.__name__, - ) - def test_should_return_same_hash_for_equal_strategy( - self, - strategy1: Imputer.Strategy, - strategy2: Imputer.Strategy, - ) -> None: - assert hash(strategy1) == hash(strategy2) - - @pytest.mark.parametrize( - ("strategy1", "strategy2"), - ([(x, y) for x in strategies() for y in strategies() if x.__class__ != y.__class__]), - ids=lambda x: x.__class__.__name__, - ) - def test_should_return_different_hash_for_unequal_strategy( - self, - strategy1: Imputer.Strategy, - strategy2: Imputer.Strategy, - ) -> None: - assert hash(strategy1) != hash(strategy2) - - -class TestEq: - - @pytest.mark.parametrize( - ("strategy1", "strategy2"), - ([(x, y) for x in strategies() for y in strategies() if x.__class__ == y.__class__]), - ids=lambda x: x.__class__.__name__, - ) - def test_equal_strategy( - self, - strategy1: Imputer.Strategy, - strategy2: Imputer.Strategy, - ) -> None: - assert strategy1 == strategy2 - - @pytest.mark.parametrize( - "strategy", - ([x for x in strategies() if x.__class__]), - ids=lambda x: x.__class__.__name__, - ) - def test_equal_identity_strategy( - self, - strategy: Imputer.Strategy, - ) -> None: - assert strategy == strategy # noqa: PLR0124 - - @pytest.mark.parametrize( - ("strategy1", "strategy2"), - ([(x, y) for x in strategies() for y in strategies() if x.__class__ != y.__class__]), - ids=lambda x: x.__class__.__name__, - ) - def test_unequal_strategy( - self, - strategy1: Imputer.Strategy, - strategy2: Imputer.Strategy, - ) -> None: - assert strategy1 != strategy2 - - -class TestSizeof: - @pytest.mark.parametrize( - "strategy", - ([Imputer.Strategy.Constant(1)]), - ids=lambda x: x.__class__.__name__, - ) - def test_sizeof_strategy( - self, - strategy: Imputer.Strategy, - ) -> None: - assert sys.getsizeof(strategy) > sys.getsizeof(object())