cloudtools / cloudtools/troposphere

object comparison with pytest produces output that isn't very useful

Open
#2,205 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
4.9k
Forks
1.4k
PR merge metrics
No merged PRs in 30d

Description

Opening to remind myself to contribute this when I get a chance unless someone beats me to it but also to discuss final formatting.

Using the following example code:

```python
"""Example."""
from troposphere import Tag, Tags

def test_tags() -> None:
"""Test tag comparison."""
assert Tags(Tag("a-tag", "test"), Tag("b-tag", "test")) == Tags(
Tag("a-tag", "test"), Tag("b-tag", "fail")
)
```

pytest will output the following for the failed assertion:

```text
def test_tags() -> None:
"""Test tag comparison."""
> assert Tags(Tag("a-tag", "test"), Tag("b-tag", "test")) == Tags(
Tag("a-tag", "test"), Tag("b-tag", "fail")
)
E AssertionError: assert ==
E + where = Tags(, )
E + where = Tag('a-tag', 'test')
E + and = Tag('b-tag', 'test')
E + and = Tags(, )
E + where = Tag('a-tag', 'test')
E + and = Tag('b-tag', 'fail')
```

This does not give a ton of easily useful info about where the comparison failed. It can be determined for this simple example because everything is defined in the test but for large, complex comparison it is not user friendly.
This experience can be improved by adding a `__repr__` method to the classes.

```python
class BaseAWSObject:

def __repr__(self) -> str:
return f"<{self.__module__}.{self.__class__.__name__}({self.to_dict()}) object at {hex(id(self))}>"

class AWSHelperFn:

def __repr__(self) -> str:
return f"<{self.__module__}.{self.__class__.__name__}({self.to_dict()}) object at {hex(id(self))}>"
```

This would produce an output of:

```
def test_tags() -> None:
"""Test tag comparison."""
> assert Tags(Tag("a-tag", "test"), Tag("b-tag", "test")) == Tags(
Tag("a-tag", "test"), Tag("b-tag", "fail")
)
E AssertionError: assert ==
E + where = Tags(, )
E + where = Tag('a-tag', 'test')
E + and = Tag('b-tag', 'test')
E + and = Tags(, )
E + where = Tag('a-tag', 'test')
E + and = Tag('b-tag', 'fail')
```

While it still does not show the exact item in the object that is failing, it does provide the data contained within the objects in the `AssertionError`.

----

The example implementation provided here mirrors the `<... object at ...>` notation of `object.__repr__()`. Should formatting be retained or should any part of it be dropped ` or just `object at ...`) or should the formatting remain as it is in the example above?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.