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/