diff --git a/changelog/3632.feature.rst b/changelog/3632.feature.rst index a08a6dd61..a715288e1 100644 --- a/changelog/3632.feature.rst +++ b/changelog/3632.feature.rst @@ -1 +1 @@ -Richer comparison information on ``AssertionError`` for objects created using `attrs `_ or `dataclasses `_ (Python 3.7+). +Richer comparison introspection on ``AssertionError`` for objects created using `attrs `_ or `dataclasses `_ (Python 3.7+). diff --git a/doc/en/example/assertion/failure_demo.py b/doc/en/example/assertion/failure_demo.py index 115fd3e22..10f8798f2 100644 --- a/doc/en/example/assertion/failure_demo.py +++ b/doc/en/example/assertion/failure_demo.py @@ -101,6 +101,30 @@ class TestSpecialisedExplanations(object): text = "head " * 50 + "f" * 70 + "tail " * 20 assert "f" * 70 not in text + def test_eq_dataclass(self): + from dataclasses import dataclass + + @dataclass + class Foo(object): + a: int + b: str + + left = Foo(1, "b") + right = Foo(1, "c") + assert left == right + + def test_eq_attrs(self): + import attr + + @attr.s + class Foo(object): + a = attr.ib() + b = attr.ib() + + left = Foo(1, "b") + right = Foo(1, "c") + assert left == right + def test_attribute(): class Foo(object): diff --git a/doc/en/example/assertion/test_failures.py b/doc/en/example/assertion/test_failures.py index 9ffe31664..30ebc72dc 100644 --- a/doc/en/example/assertion/test_failures.py +++ b/doc/en/example/assertion/test_failures.py @@ -9,5 +9,5 @@ def test_failure_demo_fails_properly(testdir): failure_demo.copy(target) failure_demo.copy(testdir.tmpdir.join(failure_demo.basename)) result = testdir.runpytest(target, syspathinsert=True) - result.stdout.fnmatch_lines(["*42 failed*"]) + result.stdout.fnmatch_lines(["*44 failed*"]) assert result.ret != 0 diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index da5d5fe97..ac83f6000 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -347,12 +347,12 @@ def _compare_eq_class(left, right, verbose, type=None): if same and verbose < 2: explanation += [u("Omitting %s identical items, use -vv to show") % len(same)] elif same: - explanation += [u("Common items:")] + explanation += [u("Common attributes:")] explanation += pprint.pformat(same).splitlines() if diff: + class_name = left.__class__.__name__ explanation += [("Differing attributes:")] for k in diff: - class_name = left.__class__.__name__ explanation += [ u("%s(%s=%r) != %s(%s=%r)") % (class_name, k, getattr(left, k), class_name, k, getattr(right, k)) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index e7f3dbaf3..8ddd96b94 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -564,7 +564,7 @@ class TestAssert_reprcompare_dataclass(object): lines = callequal(left, right) assert lines[1].startswith("Omitting 1 identical item") - assert "Common items" not in lines + assert "Common attributes" not in lines for line in lines[1:]: assert "field_a" not in line @@ -581,7 +581,7 @@ class TestAssert_reprcompare_dataclass(object): right = SimpleDataObject(1, "c") lines = callequal(left, right, verbose=2) - assert lines[1].startswith("Common items:") + assert lines[1].startswith("Common attributes:") assert "Omitting" not in lines[1] assert lines[2] == "['field_a']" @@ -598,14 +598,14 @@ class TestAssert_reprcompare_dataclass(object): right = SimpleDataObject(1, "b") lines = callequal(left, right, verbose=2) - assert lines[1].startswith("Common items:") + assert lines[1].startswith("Common attributes:") assert "Omitting" not in lines[1] assert lines[2] == "['field_a']" for line in lines[2:]: assert "field_b" not in line @pytest.mark.skipif(sys.version_info < (3, 7), reason="Dataclasses in Python3.7+") - def test_comparing_different_data_classes(self): + def test_comparing_two_different_data_classes(self): from dataclasses import dataclass @dataclass @@ -637,7 +637,7 @@ class TestAssert_reprcompare_attrsclass(object): lines = callequal(left, right) assert lines[1].startswith("Omitting 1 identical item") - assert "Common items" not in lines + assert "Common attributes" not in lines for line in lines[1:]: assert "field_a" not in line @@ -651,7 +651,7 @@ class TestAssert_reprcompare_attrsclass(object): right = SimpleDataObject(1, "c") lines = callequal(left, right, verbose=2) - assert lines[1].startswith("Common items:") + assert lines[1].startswith("Common attributes:") assert "Omitting" not in lines[1] assert lines[2] == "['field_a']" @@ -665,13 +665,13 @@ class TestAssert_reprcompare_attrsclass(object): right = SimpleDataObject(1, "b") lines = callequal(left, right, verbose=2) - assert lines[1].startswith("Common items:") + assert lines[1].startswith("Common attributes:") assert "Omitting" not in lines[1] assert lines[2] == "['field_a']" for line in lines[2:]: assert "field_b" not in line - def test_comparing_different_attrs(self): + def test_comparing_two_different_attrs_classes(self): @attr.s class SimpleDataObjectOne: field_a = attr.ib()