This is cool.

AFAIK pytest does something like this. How does your implementation differ?

What is your argument for making this part of the language? Why not a 3rd
party library?

What about asserts that are not used for testing, but as classic “unless
there’s a bug, this should hold”? Those may not want to incur the extra
cost.

—Guido

On Sun, Sep 12, 2021 at 07:09 <n...@10ne.org> wrote:

> 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 -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/T26DR4BMPG5EOB3A2ELVEWQPYRENRXHM/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
--Guido (mobile)
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/EEVHXKWUMVSEPAR73WOBQM3BO7NESPBZ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to