English 中文(简体)
漂亮打印为什么两个对象不相等
原标题:Pretty print why two objects are not equal

当使用 pytest 时, 当两个对象不等同时, 我就会得到漂亮的打印 :

Expected :Foo(id= red , other_thing= green )
Actual   :Foo(id= red , other_thing= blue )
<Click to see difference>

def test_baz():
    
        oneFoo = Foo(id="red", other_thing="blue")
        twoFoo = Foo(id="red", other_thing="green")
    
>       assert oneFoo == twoFoo
E       AssertionError: assert Foo(id= red , other_thing= blue ) == Foo(id= red , other_thing= green )
E         
E         Full diff:
E         - Foo(id= red , other_thing= green )
E         ?                            ^^ --
E         + Foo(id= red , other_thing= blue )
E         ?                            ^^^

baz.py:22: AssertionError

如果我直接在我的代码中使用一个主张,我就会得到一个 AsssetionError 和一个堆叠跟踪。

我现在正在写一些整合测试, 这些测试不是由热潮驱动的, 而是想在两个项目(特别是Pydantic数据类)不相等时, 做漂亮的打印。

问题回答

平等的实施应当使用:

例如:

class Foo:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        if isinstance(other, Foo):
            return self.x == other.x and self.y == other.y
        return False

    def __hash__(self):
        return hash((self.x, self.y))


a = Foo(1, 2)
b = Foo(1, 2)
c = Foo(3, 4)

print(a == b)
print(a == c)

my_dict = {a:  value 1 , c:  value 3 }
print(my_dict[a])

Prints:

True
False
value 1

Note

此处不需要 hash () 。 但执行这一规定是一种良好做法。

    def __hash__(self):
        return hash((self.x, self.y))

事实上,在您的代码中,这些对象并不相等, 因此是 < code> AsssertionError 。 如果您想要重写它, 使用任何文字, 使用您自己的自定义错误, 或者其它东西 。 那么您就必须在您的“ 坚固 > eq 方法中添加它 。

class Foo:
    def __init__(self, id, other_thing):
        self.id = id
        self.other_thing = other_thing

    def __eq__(self, other):
        if isinstance(other, Foo):
            return self.id == other.id and self.other_thing == other.other_thing
        return False


def test_baz():
    oneFoo = Foo(id="red", other_thing="blue")
    twoFoo = Foo(id="red", other_thing="green")
    try:
        assert oneFoo == twoFoo
    except AssertionError:
        raise ValueError(f"{oneFoo.__dict__} and {twoFoo.__dict__} are not equal.")


test_baz()



Prints

    raise ValueError(f"{oneFoo.__dict__} and {twoFoo.__dict__} are not equal.")
ValueError: { id :  red ,  other_thing :  blue } and { id :  red ,  other_thing :  green } are not equal.

这个工作很成功:

from difflib import Differ

import structlog
from colorama import Fore
from pydantic import BaseModel

logger = structlog.getLogger(__name__)

def check_equals(expected: BaseModel, actual: BaseModel) -> None:
    if not expected == actual:

        logger.error("Objects are not equal", expected=expected, actual=actual)

        diff_output = Differ().compare(
            _get_lines(expected),
            _get_lines(actual)
        )

        color_diff_output = _color_diff(diff_output)

        print("
".join(color_diff_output))

        raise ValueError("Objects not equal")

def _get_lines(item: BaseModel) -> str:
    item_json = item.model_dump_json(indent=4)
    lines = item_json.splitlines()
    return lines

def _color_diff(diff):
    """
    Found this nice function here: https://chezsoi.org/lucas/blog/colored-diff-output-with-python.html
    """
    for line in diff:
        if line.startswith( + ):
            yield Fore.GREEN + line + Fore.RESET
        elif line.startswith( - ):
            yield Fore.RED + line + Fore.RESET
        elif line.startswith( ^ ):
            yield Fore.BLUE + line + Fore.RESET
        else:
            yield line

打印 :

当您运行此代码时 :

from pydantic import BaseModel

from util.integration_test_validation.check_equals import check_equals

class Bar(BaseModel):
    beaches: int
    oranges: int

class Foo(BaseModel):
    id: str
    other_thing: str
    count: int
    bar: Bar



oneFoo = Foo(id="red", other_thing="blue", count=3, bar=Bar(beaches=5, oranges=7))
twoFoo = Foo(id="red", other_thing="green", count=3, bar=Bar(beaches=5, oranges=7))

check_equals(oneFoo, twoFoo)




相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签