Hi all,
I’d like your comments and feedback on an enhancement that introduces power
assertions to the Python language.
Proposal
--------
This feature is inspired by a similar feature of the Groovy language[1], and is
effectively a variant of the `assert` keyword.
When an assertion expression evaluates to `False`, the output shows not only
the failure, but also a breakdown of the evaluated expression from the inner
part to the outer part.
For example, a procedure like:
```python
class SomeClass:
def __init__(self):
self.val = {'d': 'e'}
def __str__(self):
return str(self.val)
sc = SomeClass()
assert sc.val['d'] == 'f'
```
Will result in the output:
```python
Assertion failed:
sc.val['d'] == f
| | |
| e False
|
{'d': 'e'}
```
See link [2] if the formatting above is screwed up.
In the output above we can see the value of every part of the expression from
left to right, mapped to their expression fragment with the pipe (`|`).
The number of rows that are printed depend on the value of each fragment of the
expression.
If the value of a fragment is longer than the actual fragment (`{'d': 'e'}` is
longer than `sc`), then the next value (`e`) will be printed on a new line
which will appear above.
Values are appended to the same line until it overflows in length to horizontal
position of the next fragment.
The information that’s displayed is dictated by the type.
If the type is a constant value, it will be displayed as is.
If the type implements `__str__`, then the return value of that will be
displayed.
It is important to note that expressions with side effects are affected by this
feature. This is because in order to display this information, we must store
references to the instances and not just the values.
Rational
--------
Every test boils down to the binary statement "Is this true or false?", whether
you use the built-in assert keyword or a more advanced assertion method
provided by a testing framework.
When an assertion fails, the output is binary too — "Expected x, but got y".
There are helpful libraries like Hamcrest which give you a more verbose
breakdown of the difference and answer the question "What exactly is the
difference between x and y?".
This is extremely helpful, but it still focuses on the difference between the
values.
We need to keep in mind that a given state is normally an outcome of a series
of states, that is, one outcome is a result of multiple conditions and causes.
This is where power assertion comes in. It allows us to better understand what
led to the failure.
Implementation
--------
I’ve already built a fully functional implementation[2] of this feature as part
of my Python testing framework - Nimoy[3].
The current implementation uses AST manipulation to remap the expression to a
data structure[4] at compile time, so that it can then be evaluated and
printed[5] at runtime.
[1]
http://docs.groovy-lang.org/next/html/documentation/core-testing-guide.html#_power_assertions
[2] https://browncoat-ninjas.github.io/nimoy/examples/#power-assertions-beta
[3] https://github.com/browncoat-ninjas/nimoy/
[4]
https://github.com/browncoat-ninjas/nimoy/blob/develop/nimoy/ast_tools/expression_transformer.py#L77
[5]
https://github.com/browncoat-ninjas/nimoy/blob/develop/nimoy/assertions/power.py
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/T26DR4BMPG5EOB3A2ELVEWQPYRENRXHM/
Code of Conduct: http://python.org/psf/codeofconduct/