mwilliamson / python-precisely

Matcher library for Python
BSD 2-Clause "Simplified" License
238 stars 11 forks source link

AllElementsMatcher still match, when iterable is empty #17

Closed JestemStefan closed 2 years ago

JestemStefan commented 2 years ago

Method all_elements using AllElementsMatcher match sucessfully (but incorrectly IMO), when provided iterable is empty.

Example:

# I want to test this method
def get_alive_objects():
    return [obj for obj in objects if obj.is_alive] # This returns empty list, because all objects are dead

some_list = get_alive_objects()

assert_that(
    some_list,
    all_elements(
        has_attrs(
            is_alive=True))
    )

Result: Matched

IMO this should throw an error that iterable is empty like, but you want to match something (like in other Matchers in iterable_matchers.py.) For example IncludesMatcher

lass IncludesMatcher(Matcher):
    def __init__(self, matchers):
        self._matchers = matchers

    def match(self, actual):
        values = _to_list_or_mismatch(actual)

        if isinstance(values, Result):
            return values
        elif len(values) == 0 and len(self._matchers) != 0: <===
            return unmatched("iterable was empty")

I can prepare PR for that if I get a greenlight

mwilliamson commented 2 years ago

This is intended behaviour, by analogy with the universal quantifier, or the behaviour of all in Python. If you want to check that the iterable is non-empty, you'll need to check for that explicitly.