https://github.com/tobywf/pytest-iterassert
Nicer asserts in pytest for asserting all or any elements or iterables (lists, generators, sets, tuples, strings)
https://github.com/tobywf/pytest-iterassert
Last synced: 4 months ago
JSON representation
Nicer asserts in pytest for asserting all or any elements or iterables (lists, generators, sets, tuples, strings)
- Host: GitHub
- URL: https://github.com/tobywf/pytest-iterassert
- Owner: tobywf
- License: mpl-2.0
- Created: 2020-05-08T06:53:21.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2020-05-11T06:33:19.000Z (about 6 years ago)
- Last Synced: 2025-10-27T03:24:23.184Z (8 months ago)
- Language: Python
- Size: 14.6 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://opensource.org/licenses/MPL-2.0)
[](https://github.com/tobywf/pytest-iterassert/actions)
[](https://codecov.io/gh/tobywf/pytest-iterassert)
[](https://github.com/psf/black)
# pytest-iterassert
Have you ever wanted to use `all` or `any` in a unit test, but found the assert
message to be lacking? Do assertions on class attributes in collections almost
make you wish you were coding in Java (with a nice assertion framework)? Then
this is the [pytest](https://docs.pytest.org/en/latest/) helper for you!
[pytest-iterassert](https://github.com/tobywf/pytest-iterassert) provides
`all_match` and `any_match` to give you nice asserts.
## Examples
The built-in [`any`](https://docs.python.org/3/library/functions.html#any) or
[`all`](https://docs.python.org/3/library/functions.html#all) can cause a lot of
sadness when tests fail:
```plain
def test_generator_without_iterassert() -> None:
> assert all(i < 1 for i in range(3))
E assert False
E + where False = all( at 0x10221a250>)
```
`all_match` and `any_match` make debugging easy by hoisting the comparison out,
and printing meaningful debug:
```plain
def test_generator_with_iterassert() -> None:
> assert all_match(range(3)) < 1
E assert all(0, 1, 2) < 1
E + where all(0, 1, 2) = all_match(range(0, 3))
E + where range(0, 3) = range(3)
```
How about a more complex example? Asserting attributes of a class instance is
pretty common.
``` plain
def test_attr_of_classes_without_iterassert() -> None:
foos = [Foo(1), Foo(2), Foo(3)]
> assert all(foo.bar < 3 for foo in foos)
E assert False
E + where False = all( at 0x10597ca50>)
```
`iterassert` makes it easy to apply functions to the iterable, and will convince
pytest to show you the result of that function!
``` plain
def test_attr_of_classes_with_iterassert_1() -> None:
foos = [Foo(1), Foo(2), Foo(3)]
> assert all_match(foos, get_bar) < 3
E assert all(9001, 9002, 9003) < 3
E + where all(9001, 9002, 9003) = all_match([, , ], get_bar)
```
It's also possible to run more complex checks against all items, by doing the
checking inside a function:
``` plain
def test_attr_of_classes_with_iterassert_2() -> None:
foos = [Foo(1), Foo(2), Foo(3)]
> assert all_match(foos, check_bar)
E assert all(False, False, False)
E + where all(False, False, False) = all_match([, , ], check_bar)
```
Note in this case, much like the buildin functions, `all_match` and `any_match`
take no operator or operand.
And, if you need to incorporate more transformations, but would like to see the
intermediary items, `capture` allows for this, too:
``` plain
def test_attr_of_classes_with_iterassert_3() -> None:
foos = [Foo(1), Foo(2), Foo(3)]
> assert all_match(capture(foo.bar for foo in foos), check_val)
E assert all(False, False, False)
E + where all(False, False, False) = all_match([9001, 9002, 9003], check_val)
E + where [9001, 9002, 9003] = capture( at 0x1031220d0>)
```
Even the test summary says it all:
``` plain
FAILED example.py::test_generator_without_iterassert - assert False
FAILED example.py::test_generator_with_iterassert - assert all(0, 1, 2) < 1
FAILED example.py::test_attr_of_classes_without_iterassert - assert False
FAILED example.py::test_attr_of_classes_with_iterassert_1 - assert all(9001, 9002, 9003) < 3
FAILED example.py::test_attr_of_classes_with_iterassert_2 - assert all(False, False, False)
FAILED example.py::test_attr_of_classes_with_iterassert_3 - assert all(False, False, False)
```
## Installation
[pytest-iterassert is on
PyPI](https://pypi.org/project/pytest-iterassert/), so you can simply install
via `pip install pytest-iterassert` (requires Python 3.6 or higher).
(If you're really brave, you can also alias `all_match` and `any_match` to the
builtin functions on import.)
## Changelog
### [0.0.3] - 2020-05-10
* Add `capture`, and allow `all_match` and `any_match` to not take an
operator/operand, for checks inside the mapping function
### [0.0.2] - 2020-05-07
* Initial release
## Development
This library uses [Poetry](https://python-poetry.org/) for managing
dependencies. You just need to run `poetry install`, and it will create a
virtual environment with all developer dependencies installed.
Please run `poetry run ./lint` before submitting pull requests.
## License
This library is licensed under the Mozilla Public License Version 2.0. For more
information, see `LICENSE`.