Source code for skcriteria.testing

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# License: BSD-3 (https://tldrlegal.com/license/bsd-3-clause-license-(revised))
# Copyright (c) 2016-2021, Cabral, Juan; Luczywo, Nadia
# Copyright (c) 2022, 2023, 2024 QuatroPe
# All rights reserved.

# =============================================================================
# DOCS
# =============================================================================

"""Public testing utility functions.

This module exposes "assert" functions which facilitate the comparison in a
testing environment of objects created in skcriteria.

The functionalities are extensions of those present in "pandas.testing" and
"numpy.testing".

"""

# =============================================================================
# IMPORTS
# =============================================================================

from .utils import hidden

with hidden():
    from .agg import ResultABC
    from .core import DecisionMatrix
    from .cmp import RanksComparator


# =============================================================================
# CONSTANTS
# =============================================================================


def _assert(cond, err_msg):
    """Asserts that a condition is true, otherwise raises an AssertionError \
    with a specified error message.

    This function exists to prevent asserts from being turned off with a
    "python -O."

    Parameters
    ----------
    cond : bool
        The condition to be evaluated.
    err_msg : str
        The error message to be raised if the condition is false.

    """
    if not cond:
        raise AssertionError(err_msg)


[docs] def assert_dmatrix_equals(left, right, **diff_kws): """Asserts that two DecisionMatrix objects are equal by comparing \ their attributes with some tolerance. Parameters ---------- left : DecisionMatrix The first DecisionMatrix object to compare. right : DecisionMatrix The second DecisionMatrix object to compare. **diff_kws : dict Additional keyword arguments to pass to the `DecisionMatrix.diff` method. Raises ------ AssertionError If the two DecisionMatrix objects are not equal. """ # Check if left is a DecisionMatrix _assert( isinstance(left, DecisionMatrix), f"'left' is not a DecisionMatrix instance. Found {type(left)!r}", ) # Check if left and right are equal diff = left.diff(right, **diff_kws) if not diff.has_differences: # if there are no differences end the test return # Check if right is a DecisionMatrix _assert( diff.right_type is DecisionMatrix, f"'right' is not a DecisionMatrix instance. Found {type(right)!r}", ) # Check wich member are different _assert("shape" not in diff.members_diff, "'shape' are not equal") _assert("criteria" not in diff.members_diff, "'criteria' are not equal") _assert( "alternatives" not in diff.members_diff, "'alternatives' are not equal" ) _assert( "objectives" not in diff.members_diff, "'objectives' are not equal" ) _assert("weights" not in diff.members_diff, "'weights' are not equal") _assert("matrix" not in diff.members_diff, "'matrix' are not equal") _assert("dtypes" not in diff.members_diff, "'dtypes' are not equal")
[docs] def assert_result_equals(left, right, **diff_kws): """Asserts that two results objects are equal by comparing their \ attributes with some tolerance. Parameters ---------- left : skcriteria.agg.ResultABC The left result to compare. right : skcriteria.agg.ResultABC The right result to compare. **diff_kws : dict Optional keyword arguments to pass to the result `diff` method. Raises ------ AssertionError if the two results are not equal. """ # Check if left is a ResultABC _assert( isinstance(left, ResultABC), f"'left' is not a ResultABC instance. Found {type(left)!r}", ) # check if left and right are equal diff = left.diff(right, **diff_kws) if not diff.has_differences: # if there are no differences end the test return # check if right is a ResultABC _assert( diff.different_types is False, f"'right' is not a ResultABC instance. Found {diff.right_type!r}", ) # Check wich member are different _assert( "alternatives" not in diff.members_diff, "'alternatives' are not equal" ) _assert( "method" not in diff.members_diff, f"'method' mismatch: Expected {left.method!r}, " f"but got {right.method!r}.", ) _assert("values" not in diff.members_diff, "'values' are not equal") _assert("extra_" not in diff.members_diff, "'extra_' are not equal")
[docs] def assert_rcmp_equals(left, right, **diff_kws): """Asserts that the left and right RankComparator objects are equal \ by comparing their attributes with some tolerance. Parameters ---------- left : RanksComparator The left object to compare. right : Any The right object to compare. **diff_kws : keyword arguments Additional keyword arguments to pass to the `diff` method. Raises ------ AssertionError If the left object is not an instance of RanksComparator. AssertionError If the right object is not an instance of RanksComparator. AssertionError If the left and right objects have different lengths. AssertionError If the ranks at any index of the left and right objects are not equal. """ # check if left is a RanksComparator _assert( isinstance(left, RanksComparator), f"'left' is not a RanksComparator instance. Found {type(left)!r}", ) # check if left and right has some difference diff = left.diff(right, **diff_kws) if not diff.has_differences: # if there are no differences end the test return # check if right is a RanksComparator _assert( diff.different_types is False, "'right' is not a RanksComparator instance. " f"Found {diff.right_type!r}", ) # check if left and right have the same length llen, rlen = len(left), len(right) _assert( llen == rlen, f"RanksComparator instances have different lengths: {llen} != {rlen}", ) # check if left and right have the same ranks enum_zip_ranks = enumerate(zip(left.ranks, right.ranks)) for idx, ((lrank_name, lrank), (rrank_name, rrank)) in enum_zip_ranks: try: _assert(lrank_name == rrank_name, "Name missmatch") assert_result_equals(lrank, rrank) except AssertionError as err: raise AssertionError(f"Mismatch at index {idx}") from err