Elegant assertions library.
This is currently a work in progress.
expecting.dict
: Dictionary assertions, combined with other assertions makes it easier to verify complex dictionary schemas.expecting.list
: Utility assertions, like order agnostic comparisons.expecting.number
: Simple number comparisons, the small building blocks for more complex structured data checking.expecting.string
: A variety of formats like date and time, URL, UUID.
pip install expecting
poetry add expecting --group dev
Expecting consists of a set of assertion objects that can be used with assert
statements in a clear, readable way.
Most common assertion will be covered under a structured set of modules, following an intuitive naming schema:
import expecting
assert '2023-10-11' == expecting.string.datetime.iso8601_day()
Here, the expcting.string.datetime
module introduces a handful of factory methods for asserting that the value is a
string representing a date and time format.
It's specially useful with pytest and its amazing error messages, where an assertion failure message would look something like:
string/test_datetime.py:7 (test_iso8601_full_matches[2023/10/11 13:01:10])
'2023/10/11 13:01:10' != ~= <datetime as "%Y-%m-%dT%H:%M:%S.%f%z">
Expected :~= <datetime as "%Y-%m-%dT%H:%M:%S.%f%z">
Actual :'2023/10/11 13:01:10'
<Click to see difference>
datetime_str = '2023/10/11 13:01:10'
@pytest.mark.parametrize(
'datetime_str',
(
'2023/10/11 13:01:10',
)
)
def test_iso8601_full_matches(datetime_str: str):
> assert datetime_str == expecting.string.datetime.iso8601_full()
E assert '2023/10/11 13:01:10' == ~= <datetime as "%Y-%m-%dT%H:%M:%S.%f%z">
...
The ~=
symbol prefixing the expected value is used denote this value is an "expecting object".
Feel free to create issues or merge requests with any improvement or fix you might find useful.
expecting.dict
expecting.list
expecting.number
expecting.string
expecting.string.datetime
expecting.string.datetime.iso8601_full
expecting.string.datetime.iso8601_millisecond
expecting.string.datetime.iso8601_second
expecting.string.datetime.iso8601_minute
expecting.string.datetime.iso8601_hour
expecting.string.datetime.iso8601_day
expecting.string.datetime.iso8601_month
expecting.string.datetime.iso8601_year
expecting.string.uuid
Asserts that a dictionary contains a sub-dictionary. Can
import expecting
current = {
'color': 'yellow',
'positions': [(1, 1), (2, 3), (4, 2)],
}
assert current == expecting.dict.containing({
'positions': expecting.list.containing([(2, 3)]),
'color': 'yellow',
})
Asserts that a list contains a sub-list. Order is important.
import expecting
current = [1, 2, 3]
assert current == expecting.list.containing([2, 3])
Asserts that a list contains all the values, disregarding their order.
import expecting
current = [1, 2, 3]
assert current == expecting.list.unordered([3, 1, 2])
Disclaimer: of course writing assert a >= 1
is much easier and should be the preferred way to.
The functions under this namespace are intended for combined usage with other expecting objects for complex schema validations.
Asserts number is greater than or equal to (>=) given value.
import expecting
assert 10 == expecting.number.ge(10)
Asserts number is lesser than or equal to (<=) given value.
import expecting
assert 10 == expecting.number.le(10)
Asserts number is greater than (>) given value.
import expecting
assert 10 == expecting.number.gt(9)
Asserts number is lesser than (<) given value.
import expecting
assert 10 == expecting.number.lt(11)
Asserts number is equals to given value.
import expecting
assert 10 == expecting.number.eq(10)
Asserts number is not equals to given value.
import expecting
assert 10 == expecting.number.ne(9)
Asserts string is a valid ISO8601 full format, considering the timezone Z or UTC offset versions.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f+000000.000000') == expecting.string.datetime.iso8601_full()
assert datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%fZ') == expecting.string.datetime.iso8601_full()
Asserts string is a valid ISO8601 format up to the milliseconds.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') == expecting.string.datetime.iso8601_millisecond()
Asserts string is a valid ISO8601 format up to the seconds
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m-%dT%H:%M:%S') == expecting.string.datetime.iso8601_second()
Asserts string is a valid ISO8601 format up to the minutes.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m-%dT%H:%M') == expecting.string.datetime.iso8601_minute()
Asserts string is a valid ISO8601 format up to the hours.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m-%dT%H') == expecting.string.datetime.iso8601_hour()
Asserts string is a valid ISO8601 format up to the day.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m-%d') == expecting.string.datetime.iso8601_day()
Asserts string is a valid ISO8601 format up to the month.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y-%m') == expecting.string.datetime.iso8601_month()
Asserts string is a valid ISO8601 format up to the Year.
from datetime import datetime
import expecting
assert datetime.now().strftime('%Y') == expecting.string.datetime.iso8601_year()
Asserts that a string is a valid UUID v1 hex
import uuid
import expecting
assert str(uuid.uuid1()) == expecting.string.uuid.v1()
Asserts that a string is a valid UUID v3 hex
import uuid
import expecting
assert str(uuid.uuid3(uuid.uuid1(), 'bogus')) == expecting.string.uuid.v3()
Asserts that a string is a valid UUID v4 hex
import uuid
import expecting
assert str(uuid.uuid4()) == expecting.string.uuid.v4()
Asserts that a string is a valid UUID v5 hex
import uuid
import expecting
assert str(uuid.uuid5(uuid.uuid1(), 'bogus')) == expecting.string.uuid.v5()
Asserts that a string is a valid UUID hex, disregarding the version.
import uuid
import expecting
assert str(uuid.uuid1()) == expecting.string.uuid.hex()
assert str(uuid.uuid3(uuid.uuid1(), 'bogus')) == expecting.string.uuid.hex()
assert str(uuid.uuid4()) == expecting.string.uuid.hex()
assert str(uuid.uuid5(uuid.uuid1(), 'bogus')) == expecting.string.uuid.hex()