Assertion library for python unit testing with a fluent API
AssertionBuilder
(val, description='', kind=None, expected=None, logger=None)¶Bases: assertpy.string.StringMixin
, assertpy.snapshot.SnapshotMixin
, assertpy.numeric.NumericMixin
, assertpy.helpers.HelpersMixin
, assertpy.file.FileMixin
, assertpy.extracting.ExtractingMixin
, assertpy.exception.ExceptionMixin
, assertpy.dynamic.DynamicMixin
, assertpy.dict.DictMixin
, assertpy.date.DateMixin
, assertpy.contains.ContainsMixin
, assertpy.collection.CollectionMixin
, assertpy.base.BaseMixin
, object
The main assertion class. Never call the constructor directly, always use the
assert_that()
helper instead. Or if you just want warning messages, use the
assert_warn()
helper.
val – the value to be tested (aka the actual value)
description (str, optional) – the extra error message description. Defaults to ''
(aka empty string)
kind (str, optional) – the kind of assertions, one of None
, soft
, or warn
.
Defaults to None
expected (Error, optional) – the expected exception. Defaults to None
logger (Logger, optional) – the logger for warning messages. Defaults to None
builder
(val, description='', kind=None, expected=None, logger=None)¶Helper to build a new AssertionBuilder
instance. Use this only if not chaining to self
.
val – the value to be tested (aka the actual value)
description (str, optional) – the extra error message description. Defaults to ''
(aka empty string)
kind (str, optional) – the kind of assertions, one of None
, soft
, or warn
.
Defaults to None
expected (Error, optional) – the expected exception. Defaults to None
logger (Logger, optional) – the logger for warning messages. Defaults to None
error
(msg)¶Helper to raise an AssertionError
with the given message.
If an error description is set by described_as()
, then that
description is prepended to the error message.
msg – the error message
Examples
Used to fail an assertion:
if self.val != other:
self.error('Expected <%s> to be equal to <%s>, but was not.' % (self.val, other))
AssertionError – always raised unless kind
is warn
(as set when using an
assert_warn()
assertion) or kind
is soft
(as set when inside a
soft_assertions()
context).
add_extension
(func)¶Add a new user-defined custom assertion to assertpy.
Once the assertion is registered with assertpy, use it like any other assertion. Pass val to
assert_that()
, and then call it.
func – the assertion function (to be added)
Examples
from assertpy import add_extension
def is_5(self):
if self.val != 5:
self.error(f'{self.val} is NOT 5!')
return self
add_extension(is_5)
def test_5():
assert_that(5).is_5()
def test_6():
assert_that(6).is_5() # fails
# 6 is NOT 5!
assert_that
(val, description='')¶Set the value to be tested, plus an optional description, and allow assertions to be called.
This is a factory method for the AssertionBuilder
, and the single most important
method in all of assertpy.
val – the value to be tested (aka the actual value)
description (str, optional) – the extra error message description. Defaults to ''
(aka empty string)
Examples
Just import it once at the top of your test file, and away you go…:
from assertpy import assert_that
def test_something():
assert_that(1 + 2).is_equal_to(3)
assert_that('foobar').is_length(6).starts_with('foo').ends_with('bar')
assert_that(['a', 'b', 'c']).contains('a').does_not_contain('x')
assert_warn
(val, description='', logger=None)¶Set the value to be tested, and optional description and logger, and allow assertions to be called, but never fail, only log warnings.
This is a factory method for the AssertionBuilder
, but unlike assert_that()
an
AssertionError is never raised, and execution is never halted. Instead, any assertion failures
results in a warning message being logged. Uses the given logger, or defaults to a simple logger
that prints warnings to stdout
.
val – the value to be tested (aka the actual value)
description (str, optional) – the extra error message description. Defaults to ''
(aka empty string)
logger (Logger, optional) – the logger for warning message on assertion failure. Defaults to None
(aka use the default simple logger that prints warnings to stdout
)
Examples
from assertpy import assert_warn
assert_warn('foo').is_length(4)
assert_warn('foo').is_empty()
assert_warn('foo').is_false()
assert_warn('foo').is_digit()
assert_warn('123').is_alpha()
Even though all of the above assertions fail, AssertionError
is never raised and
test execution is never halted. Instead, the failed assertions merely log the following
warning messages to stdout
:
2019-10-27 20:00:35 WARNING [test_foo.py:23]: Expected <foo> to be of length <4>, but was <3>.
2019-10-27 20:00:35 WARNING [test_foo.py:24]: Expected <foo> to be empty string, but was not.
2019-10-27 20:00:35 WARNING [test_foo.py:25]: Expected <False>, but was not.
2019-10-27 20:00:35 WARNING [test_foo.py:26]: Expected <foo> to contain only digits, but did not.
2019-10-27 20:00:35 WARNING [test_foo.py:27]: Expected <123> to contain only alphabetic chars, but did not.
fail
(msg='')¶Force immediate test failure with the given message.
msg (str, optional) – the failure message. Defaults to ''
Examples
Fail a test:
from assertpy import assert_that, fail
def test_fail():
fail('forced fail!')
If you wanted to test for a known failure, here is a useful pattern:
import operator
def test_adder_bad_arg():
try:
operator.add(1, 'bad arg')
fail('should have raised error')
except TypeError as e:
assert_that(str(e)).contains('unsupported operand')
remove_extension
(func)¶Remove a user-defined custom assertion.
func – the assertion function (to be removed)
Examples
from assertpy import remove_extension
remove_extension(is_5)
soft_assertions
()¶Create a soft assertion context.
Normally, any assertion failure will halt test execution immediately by raising an error. Soft assertions are way to collect assertion failures (and failure messages) together, to be raised all at once at the end, without halting your test.
Examples
Create a soft assertion context, and some failing tests:
from assertpy import assert_that, soft_assertions
with soft_assertions():
assert_that('foo').is_length(4)
assert_that('foo').is_empty()
assert_that('foo').is_false()
assert_that('foo').is_digit()
assert_that('123').is_alpha()
When the context ends, any assertion failures are collected together and a single
AssertionError
is raised:
AssertionError: soft assertion failures:
1. Expected <foo> to be of length <4>, but was <3>.
2. Expected <foo> to be empty string, but was not.
3. Expected <False>, but was not.
4. Expected <foo> to contain only digits, but did not.
5. Expected <123> to contain only alphabetic chars, but did not.
soft_fail
(msg='')¶Within a soft_assertions()
context, append the failure message to the soft error list,
but do not halt test execution.
Otherwise, outside the context, acts identical to fail()
and forces immediate test
failure with the given message.
msg (str, optional) – the failure message. Defaults to ''
Examples
Failing soft assertions:
from assertpy import assert_that, soft_assertions, soft_fail
with soft_assertions():
assert_that(1).is_equal_to(2)
soft_fail('my message')
assert_that('foo').is_equal_to('bar')
Fails, and outputs the following soft error list:
AssertionError: soft assertion failures:
1. Expected <1> to be equal to <2>, but was not.
2. Fail: my message!
3. Expected <foo> to be equal to <bar>, but was not.
BaseMixin
¶Bases: object
Base mixin.
described_as
(description)¶Describes the assertion. On failure, the description is included in the error message.
This is not an assertion itself. But if the any of the following chained assertions fail, the description will be included in addition to the regular error message.
description – the error message description
Examples
assert_that(1).described_as('error msg desc').is_equal_to(2) # fails
# [error msg desc] Expected <1> to be equal to <2>, but was not.
returns this instance to chain to the next assertion
is_equal_to
(other, **kwargs)¶Asserts that val is equal to other.
Checks actual is equal to expected using the ==
operator. When val is dict-like,
optionally ignore or include keys when checking equality.
other – the expected value
**kwargs – see below
ignore – the dict key (or list of keys) to ignore
include – the dict key (of list of keys) to include
Examples
assert_that(1 + 2).is_equal_to(3)
assert_that('foo').is_equal_to('foo')
assert_that(123).is_equal_to(123)
assert_that(123.4).is_equal_to(123.4)
assert_that(['a', 'b']).is_equal_to(['a', 'b'])
assert_that((1, 2, 3)).is_equal_to((1, 2, 3))
assert_that({'a': 1, 'b': 2}).is_equal_to({'a': 1, 'b': 2})
assert_that({'a', 'b'}).is_equal_to({'a', 'b'})
When the val is dict-like, keys can optionally be ignored when checking equality:
# ignore a single key
assert_that({'a': 1, 'b': 2}).is_equal_to({'a': 1}, ignore='b')
# ignore multiple keys
assert_that({'a': 1, 'b': 2, 'c': 3}).is_equal_to({'a': 1}, ignore=['b', 'c'])
# ignore nested keys
assert_that({'a': {'b': 2, 'c': 3, 'd': 4}}).is_equal_to({'a': {'d': 4}}, ignore=[('a', 'b'), ('a', 'c')])
When the val is dict-like, only certain keys can be included when checking equality:
# include a single key
assert_that({'a': 1, 'b': 2}).is_equal_to({'a': 1}, include='a')
# include multiple keys
assert_that({'a': 1, 'b': 2, 'c': 3}).is_equal_to({'a': 1, 'b': 2}, include=['a', 'b'])
Failure produces a nice error message:
assert_that(1).is_equal_to(2) # fails
# Expected <1> to be equal to <2>, but was not.
returns this instance to chain to the next assertion
AssertionError – if actual is not equal to expected
is_false
()¶Asserts that val is false.
Examples
assert_that(False).is_false()
assert_that(0).is_false()
assert_that('').is_false()
assert_that(0.0).is_false()
assert_that([]).is_false()
assert_that(()).is_false()
assert_that({}).is_false()
assert_that(set()).is_false()
returns this instance to chain to the next assertion
AssertionError – if val is true
is_instance_of
(some_class)¶Asserts that val is an instance of the given class.
some_class – the expected class
Examples
assert_that(1).is_instance_of(int)
assert_that('foo').is_instance_of(str)
assert_that(123.4).is_instance_of(float)
assert_that(['a', 'b']).is_instance_of(list)
assert_that((1, 2, 3)).is_instance_of(tuple)
assert_that({'a': 1, 'b': 2}).is_instance_of(dict)
assert_that({'a', 'b'}).is_instance_of(set)
assert_that(True).is_instance_of(bool)
With a user-defined class:
class Foo: pass
f = Foo()
assert_that(f).is_instance_of(Foo)
assert_that(f).is_instance_of(object)
returns this instance to chain to the next assertion
AssertionError – if val is not an instance of the given class
is_length
(length)¶Asserts that val is the given length.
Checks val is the given length using the len()
built-in.
length (int) – the expected length
Examples
assert_that('foo').is_length(3)
assert_that(['a', 'b']).is_length(2)
assert_that((1, 2, 3)).is_length(3)
assert_that({'a': 1, 'b': 2}).is_length(2)
assert_that({'a', 'b'}).is_length(2)
returns this instance to chain to the next assertion
AssertionError – if val is not the given length
is_none
()¶Asserts that val is none.
Examples
assert_that(None).is_none()
assert_that(print('hello world')).is_none()
returns this instance to chain to the next assertion
AssertionError – if val is not none
is_not_equal_to
(other)¶Asserts that val is not equal to other.
Checks actual is not equal to expected using the !=
operator.
other – the expected value
Examples
assert_that(1 + 2).is_not_equal_to(4)
assert_that('foo').is_not_equal_to('bar')
assert_that(123).is_not_equal_to(456)
assert_that(123.4).is_not_equal_to(567.8)
assert_that(['a', 'b']).is_not_equal_to(['c', 'd'])
assert_that((1, 2, 3)).is_not_equal_to((1, 2, 4))
assert_that({'a': 1, 'b': 2}).is_not_equal_to({'a': 1, 'b': 3})
assert_that({'a', 'b'}).is_not_equal_to({'a', 'x'})
returns this instance to chain to the next assertion
AssertionError – if actual is equal to expected
is_not_none
()¶Asserts that val is not none.
Examples
assert_that(0).is_not_none()
assert_that('foo').is_not_none()
assert_that(False).is_not_none()
returns this instance to chain to the next assertion
AssertionError – if val is none
is_not_same_as
(other)¶Asserts that val is not identical to other.
Checks actual is not identical to expected using the is
operator.
other – the expected value
Examples
assert_that(1).is_not_same_as(2)
assert_that('foo').is_not_same_as('bar')
assert_that(123.4).is_not_same_as(567.8)
assert_that((1, 2, 3)).is_not_same_as((1, 2, 4))
# mutable collections, even if equal, are not identical...
assert_that(['a', 'b']).is_not_same_as(['a', 'b'])
assert_that({'a': 1, 'b': 2}).is_not_same_as({'a': 1, 'b': 2})
assert_that({'a', 'b'}).is_not_same_as({'a', 'b'})
returns this instance to chain to the next assertion
AssertionError – if actual is identical to expected
is_same_as
(other)¶Asserts that val is identical to other.
Checks actual is identical to expected using the is
operator.
other – the expected value
Examples
Basic types are identical:
assert_that(1).is_same_as(1)
assert_that('foo').is_same_as('foo')
assert_that(123.4).is_same_as(123.4)
As are immutables like tuple
:
assert_that((1, 2, 3)).is_same_as((1, 2, 3))
But mutable collections like list
, dict
, and set
are not:
# these all fail...
assert_that(['a', 'b']).is_same_as(['a', 'b']) # fails
assert_that({'a': 1, 'b': 2}).is_same_as({'a': 1, 'b': 2}) # fails
assert_that({'a', 'b'}).is_same_as({'a', 'b'}) # fails
Unless they are the same object:
x = {'a': 1, 'b': 2}
y = x
assert_that(x).is_same_as(y)
returns this instance to chain to the next assertion
AssertionError – if actual is not identical to expected
is_true
()¶Asserts that val is true.
Examples
assert_that(True).is_true()
assert_that(1).is_true()
assert_that('foo').is_true()
assert_that(1.0).is_true()
assert_that(['a', 'b']).is_true()
assert_that((1, 2, 3)).is_true()
assert_that({'a': 1, 'b': 2}).is_true()
assert_that({'a', 'b'}).is_true()
returns this instance to chain to the next assertion
AssertionError – if val is false
is_type_of
(some_type)¶Asserts that val is of the given type.
some_type (type) – the expected type
Examples
assert_that(1).is_type_of(int)
assert_that('foo').is_type_of(str)
assert_that(123.4).is_type_of(float)
assert_that(['a', 'b']).is_type_of(list)
assert_that((1, 2, 3)).is_type_of(tuple)
assert_that({'a': 1, 'b': 2}).is_type_of(dict)
assert_that({'a', 'b'}).is_type_of(set)
assert_that(True).is_type_of(bool)
returns this instance to chain to the next assertion
AssertionError – if val is not of the given type
CollectionMixin
¶Bases: object
Collection assertions mixin.
is_iterable
()¶Asserts that val is iterable collection.
Examples
assert_that('foo').is_iterable()
assert_that(['a', 'b']).is_iterable()
assert_that((1, 2, 3)).is_iterable()
returns this instance to chain to the next assertion
AssertionError – if val is not iterable
is_not_iterable
()¶Asserts that val is not iterable collection.
Examples
assert_that(1).is_not_iterable()
assert_that(123.4).is_not_iterable()
assert_that(True).is_not_iterable()
assert_that(None).is_not_iterable()
returns this instance to chain to the next assertion
AssertionError – if val is iterable
is_sorted
(key=<function CollectionMixin.<lambda>>, reverse=False)¶Asserts that val is iterable and is sorted.
key (function) – the one-arg function to extract the sort comparison key. Defaults to
lambda x: x
to just compare items directly.
reverse (bool) – if True
, then comparison key is reversed. Defaults to False
.
Examples
assert_that(['a', 'b', 'c']).is_sorted()
assert_that((1, 2, 3)).is_sorted()
# with a key function
assert_that('aBc').is_sorted(key=str.lower)
# reverse order
assert_that(['c', 'b', 'a']).is_sorted(reverse=True)
assert_that((3, 2, 1)).is_sorted(reverse=True)
assert_that((1, 2, 3, 4, -5, 6)).is_sorted() # fails
# Expected <(1, 2, 3, 4, -5, 6)> to be sorted, but subset <4, -5> at index 3 is not.
returns this instance to chain to the next assertion
AssertionError – if val is not sorted
is_subset_of
(*supersets)¶Asserts that val is iterable and a subset of the given superset (or supersets).
*supersets – the expected superset (or supersets)
Examples
assert_that('foo').is_subset_of('abcdefghijklmnopqrstuvwxyz')
assert_that(['a', 'b']).is_subset_of(['a', 'b', 'c'])
assert_that((1, 2, 3)).is_subset_of([1, 2, 3, 4])
assert_that({'a': 1, 'b': 2}).is_subset_of({'a': 1, 'b': 2, 'c': 3})
assert_that({'a', 'b'}).is_subset_of({'a', 'b', 'c'})
# or multiple supersets (as comma-separated args)
assert_that('aBc').is_subset_of('abc', 'ABC')
assert_that((1, 2, 3)).is_subset_of([1, 3, 5], [2, 4, 6])
assert_that({'a': 1, 'b': 2}).is_subset_of({'a': 1, 'c': 3}) # fails
# Expected <{'a': 1, 'b': 2}> to be subset of <{'a': 1, 'c': 3}>, but <{'b': 2}> was missing.
returns this instance to chain to the next assertion
AssertionError – if val is not subset of given superset (or supersets)
ContainsMixin
¶Bases: object
Containment assertions mixin.
contains
(*items)¶Asserts that val contains the given item or items.
Checks if the collection contains the given item or items using in
operator.
*items – the item or items expected to be contained
Examples
assert_that('foo').contains('f')
assert_that('foo').contains('f', 'oo')
assert_that(['a', 'b']).contains('b', 'a')
assert_that((1, 2, 3)).contains(3, 2, 1)
assert_that({'a': 1, 'b': 2}).contains('b', 'a') # checks keys
assert_that({'a', 'b'}).contains('b', 'a')
assert_that([1, 2, 3]).is_type_of(list).contains(1, 2).does_not_contain(4, 5)
returns this instance to chain to the next assertion
AssertionError – if val does not contain the item or items
contains_duplicates
()¶Asserts that val is iterable and does contain duplicates.
Examples
assert_that('foo').contains_duplicates()
assert_that(['a', 'a', 'b']).contains_duplicates()
assert_that((1, 1, 2)).contains_duplicates()
returns this instance to chain to the next assertion
AssertionError – if val does not contain any duplicates
contains_only
(*items)¶Asserts that val contains only the given item or items.
Checks if the collection contains only the given item or items using in
operator.
*items – the only item or items expected to be contained
Examples
assert_that('foo').contains_only('f', 'o')
assert_that(['a', 'a', 'b']).contains_only('a', 'b')
assert_that((1, 1, 2)).contains_only(1, 2)
assert_that({'a': 1, 'a': 2, 'b': 3}).contains_only('a', 'b')
assert_that({'a', 'a', 'b'}).contains_only('a', 'b')
returns this instance to chain to the next assertion
AssertionError – if val contains anything not item or items
contains_sequence
(*items)¶Asserts that val contains the given ordered sequence of items.
Checks if the collection contains the given sequence of items using in
operator.
*items – the sequence of items expected to be contained
Examples
assert_that('foo').contains_sequence('f', 'o')
assert_that('foo').contains_sequence('o', 'o')
assert_that(['a', 'b', 'c']).contains_sequence('b', 'c')
assert_that((1, 2, 3)).contains_sequence(1, 2)
returns this instance to chain to the next assertion
AssertionError – if val does not contains the given sequence of items
does_not_contain
(*items)¶Asserts that val does not contain the given item or items.
Checks if the collection excludes the given item or items using in
operator.
*items – the item or items expected to be excluded
Examples
assert_that('foo').does_not_contain('x')
assert_that(['a', 'b']).does_not_contain('x', 'y')
assert_that((1, 2, 3)).does_not_contain(4, 5)
assert_that({'a': 1, 'b': 2}).does_not_contain('x', 'y') # checks keys
assert_that({'a', 'b'}).does_not_contain('x', 'y')
assert_that([1, 2, 3]).is_type_of(list).contains(1, 2).does_not_contain(4, 5)
returns this instance to chain to the next assertion
AssertionError – if val does contain the item or items
does_not_contain_duplicates
()¶Asserts that val is iterable and does not contain any duplicates.
Examples
assert_that('fox').does_not_contain_duplicates()
assert_that(['a', 'b', 'c']).does_not_contain_duplicates()
assert_that((1, 2, 3)).does_not_contain_duplicates()
returns this instance to chain to the next assertion
AssertionError – if val does contain duplicates
is_empty
()¶Asserts that val is empty.
Examples
assert_that('').is_empty()
assert_that([]).is_empty()
assert_that(()).is_empty()
assert_that({}).is_empty()
assert_that(set()).is_empty()
returns this instance to chain to the next assertion
AssertionError – if val is not empty
is_in
(*items)¶Asserts that val is equal to one of the given items.
*items – the items expected to contain val
Examples
assert_that('foo').is_in('foo', 'bar', 'baz')
assert_that(1).is_in(0, 1, 2, 3)
returns this instance to chain to the next assertion
AssertionError – if val is not in the given items
is_not_empty
()¶Asserts that val is not empty.
Examples
assert_that('foo').is_not_empty()
assert_that(['a', 'b']).is_not_empty()
assert_that((1, 2, 3)).is_not_empty()
assert_that({'a': 1, 'b': 2}).is_not_empty()
assert_that({'a', 'b'}).is_not_empty()
returns this instance to chain to the next assertion
AssertionError – if val is empty
is_not_in
(*items)¶Asserts that val is not equal to one of the given items.
*items – the items expected to exclude val
Examples
assert_that('foo').is_not_in('bar', 'baz', 'box')
assert_that(1).is_not_in(-1, -2, -3)
returns this instance to chain to the next assertion
AssertionError – if val is in the given items
DateMixin
¶Bases: object
Date and time assertions mixin.
is_after
(other)¶Asserts that val is a date and is after other date.
other – the other date, expected to be before val
Examples
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(today).is_after(yesterday)
returns this instance to chain to the next assertion
AssertionError – if val is not after the given date
is_before
(other)¶Asserts that val is a date and is before other date.
other – the other date, expected to be after val
Examples
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(yesterday).is_before(today)
returns this instance to chain to the next assertion
AssertionError – if val is not before the given date
is_equal_to_ignoring_milliseconds
(other)¶Asserts that val is a date and is equal to other date to the second.
other – the other date, expected to be equal to the second
Examples
import datetime
d1 = datetime.datetime(2020, 1, 2, 3, 4, 5, 6) # 2020-01-02 03:04:05.000006
d2 = datetime.datetime(2020, 1, 2, 3, 4, 5, 777777) # 2020-01-02 03:04:05.777777
assert_that(d1).is_equal_to_ignoring_milliseconds(d2)
returns this instance to chain to the next assertion
AssertionError – if val is not equal to the given date to the second
is_equal_to_ignoring_seconds
(other)¶Asserts that val is a date and is equal to other date to the minute.
other – the other date, expected to be equal to the minute
Examples
import datetime
d1 = datetime.datetime(2020, 1, 2, 3, 4, 5) # 2020-01-02 03:04:05
d2 = datetime.datetime(2020, 1, 2, 3, 4, 55) # 2020-01-02 03:04:55
assert_that(d1).is_equal_to_ignoring_seconds(d2)
returns this instance to chain to the next assertion
AssertionError – if val is not equal to the given date to the minute
is_equal_to_ignoring_time
(other)¶Asserts that val is a date and is equal to other date ignoring time.
other – the other date, expected to be equal ignoring time
Examples
import datetime
d1 = datetime.datetime(2020, 1, 2, 3, 4, 5) # 2020-01-02 03:04:05
d2 = datetime.datetime(2020, 1, 2, 13, 44, 55) # 2020-01-02 13:44:55
assert_that(d1).is_equal_to_ignoring_time(d2)
returns this instance to chain to the next assertion
AssertionError – if val is not equal to the given date ignoring time
DictMixin
¶Bases: object
Dict assertions mixin.
contains_entry
(*args, **kwargs)¶Asserts that val is a dict and contains the given entry or entries.
Checks if the dict contains the given key-value pair or pairs.
*args – the entry or entries expected to be contained (as {k: v}
args)
**kwargs – the entry or entries expected to be contained (as k=v
kwargs)
Examples
# using args
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry({'a': 1})
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry({'a': 1}, {'b': 2})
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry({'a': 1}, {'b': 2}, {'c': 3})
# using kwargs
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry(a=1)
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry(a=1, b=2)
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry(a=1, b=2, c=3)
# or args and kwargs
assert_that({'a': 1, 'b': 2, 'c': 3}).contains_entry({'c': 3}, a=1, b=2)
returns this instance to chain to the next assertion
AssertionError – if val does not contain the entry or entries
contains_key
(*keys)¶Asserts the val is a dict and contains the given key or keys. Alias for contains()
.
Checks if the dict contains the given key or keys using in
operator.
*keys – the key or keys expected to be contained
Examples
assert_that({'a': 1, 'b': 2}).contains_key('a')
assert_that({'a': 1, 'b': 2}).contains_key('a', 'b')
returns this instance to chain to the next assertion
AssertionError – if val does not contain the key or keys
contains_value
(*values)¶Asserts that val is a dict and contains the given value or values.
Checks if the dict contains the given value or values in any key.
*values – the value or values expected to be contained
Examples
assert_that({'a': 1, 'b': 2}).contains_value(1)
assert_that({'a': 1, 'b': 2}).contains_value(1, 2)
returns this instance to chain to the next assertion
AssertionError – if val does not contain the value or values
does_not_contain_entry
(*args, **kwargs)¶Asserts that val is a dict and does not contain the given entry or entries.
Checks if the dict excludes the given key-value pair or pairs.
*args – the entry or entries expected to be excluded (as {k: v}
args)
**kwargs – the entry or entries expected to be excluded (as k=v
kwargs)
Examples
# using args
assert_that({'a': 1, 'b': 2, 'c': 3}).does_not_contain_entry({'a': 2})
assert_that({'a': 1, 'b': 2, 'c': 3}).does_not_contain_entry({'a': 2}, {'x': 4})
# using kwargs
assert_that({'a': 1, 'b': 2, 'c': 3}).does_not_contain_entry(a=2)
assert_that({'a': 1, 'b': 2, 'c': 3}).does_not_contain_entry(a=2, x=4)
returns this instance to chain to the next assertion
AssertionError – if val does contain the entry or entries
does_not_contain_key
(*keys)¶Asserts the val is a dict and does not contain the given key or keys. Alias for does_not_contain()
.
Checks if the dict excludes the given key or keys using in
operator.
*keys – the key or keys expected to be excluded
Examples
assert_that({'a': 1, 'b': 2}).does_not_contain_key('x')
assert_that({'a': 1, 'b': 2}).does_not_contain_key('x', 'y')
returns this instance to chain to the next assertion
AssertionError – if val does contain the key or keys
does_not_contain_value
(*values)¶Asserts that val is a dict and does not contain the given value or values.
Checks if the dict excludes the given value or values across all keys.
*values – the value or values expected to be excluded
Examples
assert_that({'a': 1, 'b': 2}).does_not_contain_value(3)
assert_that({'a': 1, 'b': 2}).does_not_contain_value(3, 4)
returns this instance to chain to the next assertion
AssertionError – if val does contain the value or values
DynamicMixin
¶Bases: object
Dynamic assertions mixin.
When testing attributes of an object (or the contents of a dict), the
is_equal_to()
assertion can be a bit verbose:
fred = Person('Fred', 'Smith')
assert_that(fred.first_name).is_equal_to('Fred')
assert_that(fred.name).is_equal_to('Fred Smith')
assert_that(fred.say_hello()).is_equal_to('Hello, Fred!')
Instead, use dynamic assertions in the form of has_<name>()
where <name>
is the name of
any attribute, property, or zero-argument method on the given object. Dynamic equality
assertions test if actual is equal to expected using the ==
operator. Using dynamic
assertions, we can rewrite the above example as:
assert_that(fred).has_first_name('Fred')
assert_that(fred).has_name('Fred Smith')
assert_that(fred).has_say_hello('Hello, Fred!')
Similarly, dynamic assertions also work on any dict-like object:
fred = {
'first_name': 'Fred',
'last_name': 'Smith',
'shoe_size': 12
}
assert_that(fred).has_first_name('Fred')
assert_that(fred).has_last_name('Smith')
assert_that(fred).has_shoe_size(12)
ExceptionMixin
¶Bases: object
Expected exception mixin.
raises
(ex)¶Asserts that val is callable and set the expected exception.
Just sets the expected exception, but never calls val, and therefore never failes. You must
chain to when_called_with()
to invoke val()
.
ex – the expected exception
Examples
assert_that(some_func).raises(RuntimeError).when_called_with('foo')
returns a new instance (now with the given expected exception) to chain to the next assertion
when_called_with
(*some_args, **some_kwargs)¶Asserts that val, when invoked with the given args and kwargs, raises the expected exception.
Invokes val()
with the given args and kwargs. You must first set the expected
exception with raises()
.
*some_args – the args to call val()
**some_kwargs – the kwargs to call val()
Examples
def some_func(a):
raise RuntimeError('some error!')
assert_that(some_func).raises(RuntimeError).when_called_with('foo')
returns a new instance (now with the captured exception error message as the val) to chain to the next assertion
AssertionError – if val does not raise the expected exception
TypeError – if expected exception not set via raises()
ExtractingMixin
¶Bases: object
Collection flattening mixin.
It is often necessary to test collections of objects. Use the extracting()
helper to
reduce the collection on a given attribute. Reduce a list of objects:
alice = Person('Alice', 'Alpha')
bob = Person('Bob', 'Bravo')
people = [alice, bob]
assert_that(people).extracting('first_name').is_equal_to(['Alice', 'Bob'])
assert_that(people).extracting('first_name').contains('Alice', 'Bob')
assert_that(people).extracting('first_name').does_not_contain('Charlie')
Additionally, the extracting()
helper can accept a list of attributes to be extracted, and
will flatten them into a list of tuples. Reduce a list of objects on multiple attributes:
assert_that(people).extracting('first_name', 'last_name').contains(('Alice', 'Alpha'), ('Bob', 'Bravo'))
Also, extracting()
works on not just attributes, but also properties, and even
zero-argument methods. Reduce a list of object on properties and zero-arg methods:
assert_that(people).extracting('name').contains('Alice Alpha', 'Bob Bravo')
assert_that(people).extracting('say_hello').contains('Hello, Alice!', 'Hello, Bob!')
And extracting()
even works on dict-like objects. Reduce a list of dicts on key:
alice = {'first_name': 'Alice', 'last_name': 'Alpha'}
bob = {'first_name': 'Bob', 'last_name': 'Bravo'}
people = [alice, bob]
assert_that(people).extracting('first_name').contains('Alice', 'Bob')
Filtering
The extracting()
helper can include a filter to keep only those items for which the given
filter is truthy. For example:
users = [
{'user': 'Alice', 'age': 36, 'active': True},
{'user': 'Bob', 'age': 40, 'active': False},
{'user': 'Charlie', 'age': 13, 'active': True}
]
# filter the active users
assert_that(users).extracting('user', filter='active').is_equal_to(['Alice', 'Charlie'])
The filter can be a dict-like object and the extracted items are kept if and only if all corresponding key-value pairs are equal:
assert_that(users).extracting('user', filter={'active': False}).is_equal_to(['Bob'])
assert_that(users).extracting('user', filter={'age': 36, 'active': True}).is_equal_to(['Alice'])
Or a filter can be any function (including an in-line lambda
) that accepts as its single
argument each item in the collection, and the extracted items are kept if the function
evaluates to True
:
assert_that(users).extracting('user', filter=lambda x: x['age'] > 20)
.is_equal_to(['Alice', 'Bob'])
Sorting
The extracting()
helper can include a sort to enforce order on the extracted items.
The sort can be the name of a key (or attribute, or property, or zero-argument method) and the extracted items are ordered by the corresponding values:
assert_that(users).extracting('user', sort='age').is_equal_to(['Charlie', 'Alice', 'Bob'])
The sort can be an iterable
of names and the extracted items are ordered by
corresponding value of the first name, ties are broken by the corresponding values of the
second name, and so on:
assert_that(users).extracting('user', sort=['active', 'age']).is_equal_to(['Bob', 'Charlie', 'Alice'])
The sort can be any function (including an in-line lambda
) that accepts as its single
argument each item in the collection, and the extracted items are ordered by the corresponding
function return values:
assert_that(users).extracting('user', sort=lambda x: -x['age']).is_equal_to(['Bob', 'Alice', 'Charlie'])
extracting
(*names, **kwargs)¶Asserts that val is iterable, then extracts the named attributes, properties, or zero-arg methods into a list (or list of tuples if multiple names are given).
*names – the attribute to be extracted (or property or zero-arg method)
**kwargs – see below
filter – extract only those items where filter is truthy
sort – order the extracted items by the sort key
Examples
alice = User('Alice', 20, True)
bob = User('Bob', 30, False)
charlie = User('Charlie', 10, True)
users = [alice, bob, charlie]
assert_that(users).extracting('user').contains('Alice', 'Bob', 'Charlie')
Works with dict-like objects too:
users = [
{'user': 'Alice', 'age': 20, 'active': True},
{'user': 'Bob', 'age': 30, 'active': False},
{'user': 'Charlie', 'age': 10, 'active': True}
]
assert_that(people).extracting('user').contains('Alice', 'Bob', 'Charlie')
Filter:
assert_that(users).extracting('user', filter='active').is_equal_to(['Alice', 'Charlie'])
Sort:
assert_that(users).extracting('user', sort='age').is_equal_to(['Charlie', 'Alice', 'Bob'])
returns a new instance (now with the extracted list as the val) to chain to the next assertion
FileMixin
¶Bases: object
File assertions mixin.
does_not_exist
()¶Asserts that val is a path and that it does not exist.
Examples
assert_that('missing.txt').does_not_exist()
assert_that('missing_dir').does_not_exist()
returns this instance to chain to the next assertion
AssertionError – if val does exist
exists
()¶Asserts that val is a path and that it exists.
Examples
assert_that('myfile.txt').exists()
assert_that('mydir').exists()
returns this instance to chain to the next assertion
AssertionError – if val does not exist
is_child_of
(parent)¶Asserts that val is an existing path to a file and that file is a child of parent.
parent – the expected parent directory
Examples
assert_that('/path/to/mydir/myfile.txt').is_child_of('mydir')
assert_that('/path/to/mydir/myfile.txt').is_child_of('to')
assert_that('/path/to/mydir/myfile.txt').is_child_of('path')
returns this instance to chain to the next assertion
AssertionError – if val does not exist, or is not a file, or is not a child of the given directory
is_directory
()¶Asserts that val is a directory and that it exists.
Examples
assert_that('mydir').is_directory()
returns this instance to chain to the next assertion
AssertionError – if val does not exist, or is not a directory
is_file
()¶Asserts that val is a file and that it exists.
Examples
assert_that('myfile.txt').is_file()
returns this instance to chain to the next assertion
AssertionError – if val does not exist, or is not a file
is_named
(filename)¶Asserts that val is an existing path to a file and that file is named filename.
filename – the expected filename
Examples
assert_that('/path/to/mydir/myfile.txt').is_named('myfile.txt')
returns this instance to chain to the next assertion
AssertionError – if val does not exist, or is not a file, or is not named the given filename
contents_of
(file, encoding='utf-8')¶Helper to read the contents of the given file or path into a string with the given encoding.
file – a path-like object (aka a file name) or a file-like object (aka a file)
encoding (str) – the target encoding. Defaults to utf-8
, other useful encodings are ascii
and latin-1
.
Examples
from assertpy import assert_that, contents_of
contents = contents_of('foo.txt')
assert_that(contents).starts_with('foo').ends_with('bar').contains('oob')
returns the file contents as a string
str
IOError – if file not found
TypeError – if file is not a path-like object or a file-like object
NumericMixin
¶Bases: object
Numeric assertions mixin.
is_between
(low, high)¶Asserts that val is numeric and is between low and high.
low – the low value
high – the high value
Examples
assert_that(1).is_between(0, 2)
assert_that(123.4).is_between(111.1, 222.2)
For dates, works as expected:
import datetime
today = datetime.datetime.now()
middle = today - datetime.timedelta(hours=12)
yesterday = today - datetime.timedelta(days=1)
assert_that(middle).is_between(yesterday, today)
returns this instance to chain to the next assertion
AssertionError – if val is not between low and high
is_close_to
(other, tolerance)¶Asserts that val is numeric and is close to other within tolerance.
other – the other value, expected to be close to val within tolerance
tolerance – the tolerance
Examples
assert_that(123).is_close_to(100, 25)
assert_that(123.4).is_close_to(123, 0.5)
For dates, works as expected:
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(today).is_close_to(yesterday, datetime.timedelta(hours=36))
returns this instance to chain to the next assertion
AssertionError – if val is not close to other within tolerance
is_greater_than
(other)¶Asserts that val is numeric and is greater than other.
other – the other date, expected to be less than val
Examples
assert_that(1).is_greater_than(0)
assert_that(123.4).is_greater_than(111.1)
For dates, behavior is identical to is_after()
:
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(today).is_greater_than(yesterday)
returns this instance to chain to the next assertion
AssertionError – if val is not greater than other
is_greater_than_or_equal_to
(other)¶Asserts that val is numeric and is greater than or equal to other.
other – the other date, expected to be less than or equal to val
Examples
assert_that(1).is_greater_than_or_equal_to(0)
assert_that(1).is_greater_than_or_equal_to(1)
assert_that(123.4).is_greater_than_or_equal_to(111.1)
For dates, behavior is identical to is_after()
except when equal:
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(today).is_greater_than_or_equal_to(yesterday)
assert_that(today).is_greater_than_or_equal_to(today)
returns this instance to chain to the next assertion
AssertionError – if val is not greater than or equal to other
is_inf
()¶Asserts that val is real number and is Inf
(infinity).
Examples
assert_that(float('inf')).is_inf()
assert_that(float('inf') * 1).is_inf()
returns this instance to chain to the next assertion
AssertionError – if val is not Inf
is_less_than
(other)¶Asserts that val is numeric and is less than other.
other – the other date, expected to be greater than val
Examples
assert_that(0).is_less_than(1)
assert_that(123.4).is_less_than(555.5)
For dates, behavior is identical to is_before()
:
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(yesterday).is_less_than(today)
returns this instance to chain to the next assertion
AssertionError – if val is not less than other
is_less_than_or_equal_to
(other)¶Asserts that val is numeric and is less than or equal to other.
other – the other date, expected to be greater than or equal to val
Examples
assert_that(1).is_less_than_or_equal_to(0)
assert_that(1).is_less_than_or_equal_to(1)
assert_that(123.4).is_less_than_or_equal_to(100.0)
For dates, behavior is identical to is_before()
except when equal:
import datetime
today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)
assert_that(yesterday).is_less_than_or_equal_to(today)
assert_that(today).is_less_than_or_equal_to(today)
returns this instance to chain to the next assertion
AssertionError – if val is not less than or equal to other
is_nan
()¶Asserts that val is real number and is NaN
(not a number).
Examples
assert_that(float('nan')).is_nan()
assert_that(float('inf') * 0).is_nan()
returns this instance to chain to the next assertion
AssertionError – if val is not NaN
is_negative
()¶Asserts that val is numeric and is less than zero.
Examples
assert_that(-1).is_negative()
assert_that(-123.4).is_negative()
returns this instance to chain to the next assertion
AssertionError – if val is not negative
is_not_between
(low, high)¶Asserts that val is numeric and is not between low and high.
low – the low value
high – the high value
Examples
assert_that(1).is_not_between(2, 3)
assert_that(1.1).is_not_between(2.2, 3.3)
returns this instance to chain to the next assertion
AssertionError – if val is between low and high
is_not_close_to
(other, tolerance)¶Asserts that val is numeric and is not close to other within tolerance.
other – the other value
tolerance – the tolerance
Examples
assert_that(123).is_not_close_to(100, 22)
assert_that(123.4).is_not_close_to(123, 0.1)
returns this instance to chain to the next assertion
AssertionError – if val is close to other within tolerance
is_not_inf
()¶Asserts that val is real number and is not Inf
(infinity).
Examples
assert_that(0).is_not_inf()
assert_that(123.4).is_not_inf()
assert_that(float('nan')).is_not_inf()
returns this instance to chain to the next assertion
AssertionError – if val is Inf
is_not_nan
()¶Asserts that val is real number and is not NaN
(not a number).
Examples
assert_that(0).is_not_nan()
assert_that(123.4).is_not_nan()
assert_that(float('inf')).is_not_nan()
returns this instance to chain to the next assertion
AssertionError – if val is NaN
is_not_zero
()¶Asserts that val is numeric and is not zero.
Examples
assert_that(1).is_not_zero()
assert_that(123.4).is_not_zero()
returns this instance to chain to the next assertion
AssertionError – if val is zero
is_positive
()¶Asserts that val is numeric and is greater than zero.
Examples
assert_that(1).is_positive()
assert_that(123.4).is_positive()
returns this instance to chain to the next assertion
AssertionError – if val is not positive
is_zero
()¶Asserts that val is numeric and is zero.
Examples
assert_that(0).is_zero()
returns this instance to chain to the next assertion
AssertionError – if val is not zero
SnapshotMixin
¶Bases: object
Snapshot mixin.
Take a snapshot of a python data structure, store it on disk in JSON format, and automatically compare the latest data to the stored data on every test run.
Functional testing (which snapshot testing falls under) is very much blackbox testing. When something goes wrong, it’s hard to pinpoint the issue, because functional tests typically provide minimal isolation as compared to unit tests. On the plus side, snapshots typically do provide enormous leverage as a few well-placed snapshot tests can strongly verify that an application is working. Similar coverage would otherwise require dozens if not hundreds of unit tests.
On-disk Format
Snapshots are stored in a readable JSON format. For example:
assert_that({'a': 1, 'b': 2, 'c': 3}).snapshot()
Would be stored as:
{
"a": 1,
"b": 2,
"c": 3
}
The JSON formatting support most python data structures (dict, list, object, etc), but not custom binary data.
Updating
It’s easy to update your snapshots…just delete them all and re-run the test suite to regenerate all snapshots.
snapshot
(id=None, path='__snapshots')¶Asserts that val is identical to the on-disk snapshot stored previously.
On the first run of a test before the snapshot file has been saved, a snapshot is created, stored to disk, and the test always passes. But on all subsequent runs, val is compared to the on-disk snapshot, and the test fails if they don’t match.
Snapshot artifacts are stored in the __snapshots
directory by default, and should be
committed to source control alongside any code changes.
Snapshots are identified by test filename plus line number by default.
id – the item or items expected to be contained
path – the item or items expected to be contained
Examples
assert_that(None).snapshot()
assert_that(True).snapshot()
assert_that(1).snapshot()
assert_that(123.4).snapshot()
assert_that('foo').snapshot()
assert_that([1, 2, 3]).snapshot()
assert_that({'a': 1, 'b': 2, 'c': 3}).snapshot()
assert_that({'a', 'b', 'c'}).snapshot()
assert_that(1 + 2j).snapshot()
assert_that(someobj).snapshot()
By default, snapshots are identified by test filename plus line number. Alternately, you can specify a custom identifier using the id
arg:
assert_that({'a': 1, 'b': 2, 'c': 3}).snapshot(id='foo-id')
By default, snapshots are stored in the __snapshots
directory. Alternately, you can specify a custom path using the path
arg:
assert_that({'a': 1, 'b': 2, 'c': 3}).snapshot(path='my-custom-folder')
returns this instance to chain to the next assertion
AssertionError – if val does not equal to on-disk snapshot
StringMixin
¶Bases: object
String assertions mixin.
contains_ignoring_case
(*items)¶Asserts that val is string and contains the given item or items.
Walks val and checks for item or items using the ==
operator and str.lower()
.
*items – the item or items expected to be contained
Examples
assert_that('foo').contains_ignoring_case('F', 'oO')
assert_that(['a', 'B']).contains_ignoring_case('A', 'b')
assert_that({'a': 1, 'B': 2}).contains_ignoring_case('A', 'b')
assert_that({'a', 'B'}).contains_ignoring_case('A', 'b')
returns this instance to chain to the next assertion
AssertionError – if val does not contain the case-insensitive item or items
does_not_match
(pattern)¶Asserts that val is string and does not match the given regex pattern.
pattern (str) – the regular expression pattern, as raw string (aka prefixed with r
)
Examples
assert_that('foo').does_not_match(r'\d+')
assert_that('123').does_not_match(r'\w+')
returns this instance to chain to the next assertion
AssertionError – if val does match pattern
ends_with
(suffix)¶Asserts that val is string or iterable and ends with suffix.
suffix – the suffix
Examples
assert_that('foo').ends_with('oo')
assert_that(['a', 'b', 'c']).ends_with('c')
assert_that((1, 2, 3)).ends_with(3)
assert_that(((1, 2), (3, 4), (5, 6))).ends_with((5, 6))
returns this instance to chain to the next assertion
AssertionError – if val does not end with suffix
is_alpha
()¶Asserts that val is non-empty string and all characters are alphabetic (using str.isalpha()
).
Examples
assert_that('foo').is_lower()
returns this instance to chain to the next assertion
AssertionError – if val is not lowercase
is_digit
()¶Asserts that val is non-empty string and all characters are digits (using str.isdigit()
).
Examples
assert_that('1234567890').is_digit()
returns this instance to chain to the next assertion
AssertionError – if val is not digits
is_equal_to_ignoring_case
(other)¶Asserts that val is a string and is case-insensitive equal to other.
Checks actual is equal to expected using the ==
operator and str.lower()
.
other – the expected value
Examples
assert_that('foo').is_equal_to_ignoring_case('FOO')
assert_that('FOO').is_equal_to_ignoring_case('foo')
assert_that('fOo').is_equal_to_ignoring_case('FoO')
returns this instance to chain to the next assertion
AssertionError – if actual is not case-insensitive equal to expected
is_lower
()¶Asserts that val is non-empty string and all characters are lowercase (using str.lower()
).
Examples
assert_that('foo').is_lower()
returns this instance to chain to the next assertion
AssertionError – if val is not lowercase
is_unicode
()¶Asserts that val is a unicode string.
Examples
assert_that(u'foo').is_unicode() # python 2
assert_that('foo').is_unicode() # python 3
returns this instance to chain to the next assertion
AssertionError – if val is not a unicode string
is_upper
()¶Asserts that val is non-empty string and all characters are uppercase (using str.upper()
).
Examples
assert_that('FOO').is_upper()
returns this instance to chain to the next assertion
AssertionError – if val is not uppercase
matches
(pattern)¶Asserts that val is string and matches the given regex pattern.
pattern (str) – the regular expression pattern, as raw string (aka prefixed with r
)
Examples
assert_that('foo').matches(r'\w')
assert_that('123-456-7890').matches(r'\d{3}-\d{3}-\d{4}')
Match is partial unless anchored, so these assertion pass:
assert_that('foo').matches(r'\w')
assert_that('foo').matches(r'oo')
assert_that('foo').matches(r'\w{2}')
To match the entire string, just use an anchored regex pattern where ^
and $
match the start and end of line and \A
and \Z
match the start and end of string:
assert_that('foo').matches(r'^\w{3}$')
assert_that('foo').matches(r'\A\w{3}\Z')
And regex flags, such as re.MULTILINE
and re.DOTALL
, can only be applied via
inline modifiers, such as (?m)
and (?s)
:
s = '''bar
foo
baz'''
# using multiline (?m)
assert_that(s).matches(r'(?m)^foo$')
# using dotall (?s)
assert_that(s).matches(r'(?s)b(.*)z')
returns this instance to chain to the next assertion
AssertionError – if val does not match pattern
starts_with
(prefix)¶Asserts that val is string or iterable and starts with prefix.
prefix – the prefix
Examples
assert_that('foo').starts_with('fo')
assert_that(['a', 'b', 'c']).starts_with('a')
assert_that((1, 2, 3)).starts_with(1)
assert_that(((1, 2), (3, 4), (5, 6))).starts_with((1, 2))
returns this instance to chain to the next assertion
AssertionError – if val does not start with prefix