Extracting¶
Extract attributes, keys, or zero-arg method results from each item in an iterable.
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 ¶
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).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*names
|
object
|
the attribute to be extracted (or property or zero-arg method) |
()
|
**kwargs
|
object
|
see below |
{}
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
filter |
str | dict | Callable | None
|
extract only those items where filter is truthy |
sort |
str | Iterable | Callable | None
|
order the extracted items by the sort key |
Examples:
Usage:
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:
| Name | Type | Description |
|---|---|---|
AssertionBuilder |
Self
|
returns a new instance (extracted list as val) to chain the next assertion |
Source code in assertpy2/extracting.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |