Elegant assertions library
Project description
expecting
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.enum: Enum related assertions, checking values, names, or instances.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.
Installation options
pip install expecting
poetry add expecting --group dev
Usage
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".
Contributing
Feel free to create issues or merge requests with any improvement or fix you might find useful.
API reference
expecting.dictexpecting.enumexpecting.listexpecting.numberexpecting.stringexpecting.string.datetimeexpecting.string.datetime.iso8601_fullexpecting.string.datetime.iso8601_millisecondexpecting.string.datetime.iso8601_secondexpecting.string.datetime.iso8601_minuteexpecting.string.datetime.iso8601_hourexpecting.string.datetime.iso8601_dayexpecting.string.datetime.iso8601_monthexpecting.string.datetime.iso8601_year
expecting.string.urlexpecting.string.uuid
expecting.dict
expecting.dict.containing
Asserts that a dictionary contains a sub-dictionary.
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',
})
expecting.enum
expecting.enum.any_value_of
Asserts that a value represents a specific enum.
import expecting
from enum import Enum
class AnyEnum(str, Enum):
OK = 'OK'
assert 'OK' == expecting.enum.any_value_of(AnyEnum)
assert 'NOK' != expecting.enum.any_value_of(AnyEnum)
expecting.list
expecting.list.containing
Asserts that a list contains a sub-list. Order is important.
import expecting
current = [1, 2, 3]
assert current == expecting.list.containing([2, 3])
expecting.list.unordered
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])
expecting.number
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.
expecting.number.any
Asserts any type of number.
import expecting.number
assert 1 == expecting.number.any()
assert 0 == expecting.number.any()
assert -1.4 == expecting.number.any()
assert 'inf' == expecting.number.any()
expecting.number.ge
Asserts number is greater than or equal to (>=) given value.
import expecting
assert 10 == expecting.number.ge(10)
expecting.number.le
Asserts number is lesser than or equal to (<=) given value.
import expecting
assert 10 == expecting.number.le(10)
expecting.number.gt
Asserts number is greater than (>) given value.
import expecting
assert 10 == expecting.number.gt(9)
expecting.number.lt
Asserts number is lesser than (<) given value.
import expecting
assert 10 == expecting.number.lt(11)
expecting.number.eq
Asserts number is equals to given value.
import expecting
assert 10 == expecting.number.eq(10)
expecting.number.ne
Asserts number is not equals to given value.
import expecting
assert 10 == expecting.number.ne(9)
expecting.string
expecting.string.datetime
expecting.string.datetime.iso8601_full
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()
expecting.string.datetime.iso8601_millisecond
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()
expecting.string.datetime.iso8601_second
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()
expecting.string.datetime.iso8601_minute
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()
expecting.string.datetime.iso8601_hour
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()
expecting.string.datetime.iso8601_day
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()
expecting.string.datetime.iso8601_month
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()
expecting.string.datetime.iso8601_year
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()
expecting.string.url
expecting.string.url.with_scheme
Assert that a string is a valid URL with the given scheme.
import expecting
assert 'https://example.com' == expecting.string.url.with_scheme('https')
expecting.string.url.with_netloc
Assert that a string is a valid URL with the given netloc (host and optionally port).
import expecting
assert 'https://example.com:8080' == expecting.string.url.with_netloc('example.com:8080')
assert 'https://example.com' == expecting.string.url.with_netloc('example.com')
assert 'http://example.com' == expecting.string.url.with_netloc('example.com')
expecting.string.url.with_path
Assert that a string is a valid URL with the given path.
import expecting
assert 'https://example.com/' == expecting.string.url.with_path('/')
assert 'https://example.com' == expecting.string.url.with_path('')
assert 'https://example.com/some/subfolder' == expecting.string.url.with_path('/some/subfolder')
expecting.string.url.with_query
Assert that a string is a valid URL with the given query string.
import expecting
assert 'http://example.com?key=value' == expecting.string.url.with_query('key=value')
assert 'http://example.com?key=value&other' == expecting.string.url.with_query('key=value&other')
assert 'http://example.com?' == expecting.string.url.with_query('')
assert 'http://example.com' == expecting.string.url.with_query('')
expecting.string.url.with_fragment
Assert that a string is a valid URL with the given fragment.
import expecting
assert 'https://example.com/path#anchor' == expecting.string.url.with_fragment('anchor')
assert 'https://example.com/path#' == expecting.string.url.with_fragment('')
assert 'https://example.com/path' == expecting.string.url.with_fragment('')
assert 'https://example.com' == expecting.string.url.with_fragment('')
expecting.string.url.with_components
Assert that a string is a valid URL with the given components.
import expecting
assert 'https://example.com/path?query=1#anchor' == expecting.string.url.with_components(
scheme='https',
netloc='example.com',
path='/path',
query='query=1',
fragment='anchor',
)
expecting.string.url.any
Assert that a string is a valid URL.
import expecting
assert 'https://example.com/path?query=1#anchor' == expecting.string.url.any()
assert 'ws://127.0.0.1/ws/' == expecting.string.url.any()
expecting.string.uuid
expecting.string.uuid.v1
Asserts that a string is a valid UUID v1 hex
import uuid
import expecting
assert str(uuid.uuid1()) == expecting.string.uuid.v1()
expecting.string.uuid.v3
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()
expecting.string.uuid.v4
Asserts that a string is a valid UUID v4 hex
import uuid
import expecting
assert str(uuid.uuid4()) == expecting.string.uuid.v4()
expecting.string.uuid.v5
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()
expecting.string.uuid.hex
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()
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file expecting-0.0.8.tar.gz.
File metadata
- Download URL: expecting-0.0.8.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.12.12 Linux/6.11.0-1018-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
635751cd4da323fa2a0a8900d59ad7e64f89cde62cde44638d00adb784e9c8b0
|
|
| MD5 |
636a2ca8120b2b75ae7539af2d7ded2b
|
|
| BLAKE2b-256 |
a3c3cce3d8162dee806d5ef9eb468767671c9066c9cfa08685ebf8f1ca9d7be6
|
File details
Details for the file expecting-0.0.8-py3-none-any.whl.
File metadata
- Download URL: expecting-0.0.8-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.12.12 Linux/6.11.0-1018-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57a3aeb51d2584f192c1e76dd6ecd54270181a52252ffe5de6d0e611e3759fcd
|
|
| MD5 |
b43c2cff76a7bb1853f9debaab4af24e
|
|
| BLAKE2b-256 |
6dcb80cc44c6bd6fdef18a8a9cf7a4377104f9dbb940dcfcc4e61b3c5a45ba22
|