示例#1
0
def assert_bool_diff(assert_method, frame_locals):
    # type: (str, dict) -> tuple
    hint = None
    expected = assert_method == "assertTrue"
    actual = frame_locals["expr"]

    if not isinstance(actual, bool):
        booly = "falsy" if assert_method == "assertTrue" else "truthy"
        hint = "{expr} is {booly}".format(
            expr=deleted_text(pformat(actual)),
            booly=deleted_text(booly),
        )

    return pformat(expected), pformat(actual), hint
示例#2
0
def assert_has_calls_diff(assert_method, mock_instance, mock_name,
                          frame_locals):
    # type: (str, Mock, str, dict) -> tuple
    hint = None
    expected_calls = frame_locals["expected"]

    # expected is a normal list, mock call_args_list is a CallList so we coerce to a
    # normal list for consistent formatting
    expected = pformat(expected_calls, width=1).replace("call", mock_name)
    actual = pformat(list(mock_instance.call_args_list),
                     width=1).replace("call", mock_name)

    if not mock_instance.call_count == len(expected_calls):
        expected_line = MOCK_CALL_COUNT_MSG.format(
            padding=PADDED_NEWLINE,
            label=header_text("Expected: "),
            mock_name=header_text(mock_name),
            num=deleted_text(len(expected_calls)),
        )
        actual_line = MOCK_CALL_COUNT_MSG.format(
            padding=" " * 12,
            label=header_text("Actual: "),
            mock_name=header_text(mock_name),
            num=inserted_text(mock_instance.call_count),
        )
        hint = "\n".join([
            "expected and actual call counts differ",
            expected_line,
            actual_line,
        ])

    return expected, actual, hint
示例#3
0
def build_args_diff(expected, actual):
    # type: (tuple, tuple) -> tuple
    """
    Loops through expected/actual arg tuples and builds out the diff between each
    individual pair of args.

    :param expected: the expected called args tuple
    :param actual: the actual called args tuple
    :return: colorized, formatted diff str
    """
    i = 0
    expected_args = []
    actual_args = []
    hints = []

    expected_length = len(expected)
    actual_length = len(actual)

    while not (i == expected_length or i == actual_length):
        a = expected[i]
        b = actual[i]

        if type(expected) is not type(actual):
            hints.append(
                "Arg {num} expected type: {etype}, actual type: {atype}".
                format(
                    num=i + 1,
                    etype=deleted_text(type(expected)),
                    atype=inserted_text(type(actual)),
                ))

        act, exp = build_split_diff(pformat(b), pformat(a))
        expected_args.append("\n".join(exp))
        actual_args.append("\n".join(act))

        i += 1

    # handle different arg lengths
    if i == actual_length and i < expected_length:
        for remaining_arg in expected[i:]:
            expected_args.append(deleted_text(pformat(remaining_arg)))

    if i == expected_length and i < actual_length:
        for remaining_arg in actual[i:]:
            actual_args.append(inserted_text(pformat(remaining_arg)))

    return expected_args, actual_args
示例#4
0
def build_split_diff(lhs_repr, rhs_repr):
    # type: (str, str) -> tuple
    """
    Copy pasted from pytest-clarity.

    Compares string representations of expected and actual, building the colorized
    diff output for consumption.

    :param lhs_repr: the string representation of the "left" i.e. expected
    :param rhs_repr: the string representation of the "right" i.e. actual
    :return: tuple of the "left" and "right" colorized newline separated strings
    """
    lhs_out, rhs_out = "", ""

    matcher = difflib.SequenceMatcher(None, lhs_repr, rhs_repr)
    for op, i1, i2, j1, j2 in matcher.get_opcodes():

        lhs_substring_lines = lhs_repr[i1:i2].splitlines()
        rhs_substring_lines = rhs_repr[j1:j2].splitlines()

        for i, lhs_substring in enumerate(lhs_substring_lines):
            if op == "replace":
                lhs_out += inserted_text(lhs_substring)
            elif op == "delete":
                lhs_out += inserted_text(lhs_substring)
            elif op == "insert":
                lhs_out += Colour.stop + lhs_substring
            elif op == "equal":
                lhs_out += Colour.stop + lhs_substring

            if i != len(lhs_substring_lines) - 1:
                lhs_out += "\n"

        for j, rhs_substring in enumerate(rhs_substring_lines):
            if op == "replace":
                rhs_out += deleted_text(rhs_substring)
            elif op == "insert":
                rhs_out += deleted_text(rhs_substring)
            elif op == "equal":
                rhs_out += Colour.stop + rhs_substring

            if j != len(rhs_substring_lines) - 1:
                rhs_out += "\n"

    return lhs_out.splitlines(), rhs_out.splitlines()
示例#5
0
def get_assert_equal_diff(assert_method, frame_locals):
    # type: (str, dict) -> tuple
    expected_key, actual_key = FRAME_LOCALS_EXPECTED_ACTUAL_KEYS[assert_method]

    hint = None
    expected_value = frame_locals[expected_key]
    actual_value = frame_locals[actual_key]

    expected_type = type(expected_value)
    actual_type = type(actual_value)

    expected_pformat_kwargs = {}  # type: dict
    actual_pformat_kwargs = {}  # type: dict

    not_comparison = {
        "assertNotEqual": ("!=", "=="),
        "assertIsNot": ("is not", "is"),
    }.get(assert_method)
    if not_comparison is not None:
        expected_op, actual_op = not_comparison
        comparison = partial(
            "{expected} {op} {actual}".format,
            expected=pformat(expected_value),
            actual=pformat(actual_value),
        )
        expected = comparison(op=expected_op)
        actual = comparison(op=actual_op)
        return expected, actual, hint

    if isinstance(expected_value, dict):
        expected_pformat_kwargs["width"] = 1
    if isinstance(actual_value, dict):
        actual_pformat_kwargs["width"] = 1

    if expected_type is not actual_type:
        hint_expected = TYPE_MISMATCH_HINT_MSG.format(
            padding=PADDED_NEWLINE,
            label=header_text("Expected:"),
            vtype=deleted_text(expected_type),
        )
        hint_actual = TYPE_MISMATCH_HINT_MSG.format(
            padding=" " * 12,
            label=header_text("Actual:"),
            vtype=inserted_text(actual_type),
        )
        hint = "\n".join([
            "expected and actual are different types",
            hint_expected,
            hint_actual,
        ])

    expected = pformat(expected_value, **expected_pformat_kwargs)
    actual = pformat(actual_value, **actual_pformat_kwargs)

    return expected, actual, hint
示例#6
0
def assert_is_instance_diff(assert_method, frame_locals):
    # type: (str, dict) -> tuple
    hint = None
    expected = frame_locals["cls"]
    actual_value = frame_locals["obj"]
    actual = actual_value.__class__.__mro__

    hint_verb = {
        "assertIsInstance": "is not",
        "assertNotIsInstance": "is",
    }[assert_method]

    hint = "{actual} {verb} an instance of {expected}.".format(
        actual=header_text(actual_value),
        verb=deleted_text(hint_verb),
        expected=header_text(expected),
    )

    return pformat(expected, width=1), pformat(actual, width=1), hint