Expyct
Partial matching of any Python object.
Using Expyct is a good idea when you need to assert something in a test case but there is some non-determinism.
For example, rounding errors prevent you from comparing a float
exactly. Or a timestamp is created on-the-fly, and therefore changes every test run.
In these cases, you need to be able to set specific constraints on the expected value. That is what Expyct is for!
The constraints can be provided as constructor arguments. For example n == Number(min=3, max=5)
is only true when n
is between 3 and 5.
Some other examples of classes are Float
, String
, Any
and DateTime
. As you can see, they closely match the built-in Python types.
The library also comes with many commonly used data validators like ANY_UUID
which matches any UUID string. And TODAY
which matches any datetime occurring on the current day.
Checking nested data structures is easy as well:
import expyct as exp
from datetime import datetime
def test_my_function():
result = my_function()
assert result == {
"first_name": exp.String(regex="(mary)|(peter)", ignore_case=True),
"last_name": "Johnson",
"signup_date": exp.DateTime(after=datetime(2020, 1, 2), before=datetime(2020, 3, 5)),
"details": {
"number": exp.Int(min=2),
"amount": exp.Float(close_to=2.3, error=0.001),
"purchases": exp.List(exp.Dict(keys={"id", "product", "category"}), non_empty=True),
},
"time_of_purchase": exp.OneOf([exp.TODAY, exp.THIS_HOUR]),
"type": exp.AnyType(subclass_of=str),
"item_ids": exp.Set(subset_of=[1, 2, 3]),
"metadata": exp.Dict(keys_any=exp.Collection(superset_of=["a", "b"])),
"context": exp.ANY,
}