A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil contexts
=============== Diff against KernelTests-jar.448 ===============
Item was added: + ----- Method: ContextTest>>testBlockCannotReturnToNil (in category 'tests') ----- + testBlockCannotReturnToNil + "Test if #return:from: correctly handles returns to dead or nil contexts." + + | context nextContext | + context := [] asContext. + + "assert p is at the last instruction, i.e. a return, and is about to return to a nil context" + self assert: context method selector = thisContext method selector. + self assert: context sender isNil. + self assert: context willReturn. + self assert: context atEnd. + + nextContext := context step. "step into a return to a nil sender" + + self assert: nextContext method selector = #cannotReturn:!
+1 provided that no one objects against this breaking change after a couple of days (see https://lists.squeakfoundation.org/archives/list/squeak-dev@lists.squeakfoun...).
And you omitted two chances for #assert:equals: again. But maybe that's a style questions only. After all, we are obfuscating our tests and testing framework by duplicating basic protocols from the rest of the systems, for the sole purpose of generating better assertion error messages. :-) I agree with Eliot when he suggested a couple of years ago to use metaprogramming for generating these messages instead (I can try to find that thread again when you're interested).
Best, Christoph
--- Sent from Squeak Inbox Talk
On 2024-01-02T11:28:09+00:00, commits@source.squeak.org wrote:
A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil contexts
=============== Diff against KernelTests-jar.448 ===============
Item was added:
- ----- Method: ContextTest>>testBlockCannotReturnToNil (in category 'tests') -----
- testBlockCannotReturnToNil
- "Test if #return:from: correctly handles returns to dead or nil contexts."
- | context nextContext |
- context := [] asContext.
- "assert p is at the last instruction, i.e. a return, and is about to return to a nil context"
- self assert: context method selector = thisContext method selector.
- self assert: context sender isNil.
- self assert: context willReturn.
- self assert: context atEnd.
- nextContext := context step. "step into a return to a nil sender"
- self assert: nextContext method selector = #cannotReturn:!
Hi Christoph,
On 02-Jan-24 8:10:55 PM, christoph.thiede@student.hpi.uni-potsdam.de wrote:
+1 provided that no one objects against this breaking change after a couple of days (see https://lists.squeakfoundation.org/archives/list/squeak-dev@lists.squeakfoun...).
And you omitted two chances for #assert:equals: again. But maybe that's a style questions only. After all, we are obfuscating our tests and testing framework by duplicating basic protocols from the rest of the systems, for the sole purpose of generating better assertion error messages. :-) I agree with Eliot when he suggested a couple of years ago to use metaprogramming for generating these messages instead (I can try to find that thread again when you're interested).
Yes please, if you don't mind. Thanks!
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
On 2024-01-02T11:28:09+00:00, commits@source.squeak.org wrote:
A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil contexts
=============== Diff against KernelTests-jar.448 ===============
Item was added:
- ----- Method: ContextTest>>testBlockCannotReturnToNil (in category
'tests') -----
- testBlockCannotReturnToNil
"Test if #return:from: correctly handles returns to dead or nil
contexts."
| context nextContext |
context := [] asContext.
"assert p is at the last instruction, i.e. a return, and is
about to return to a nil context"
self assert: context method selector = thisContext method
selector.
self assert: context sender isNil.
self assert: context willReturn.
self assert: context atEnd.
nextContext := context step. "step into a return to a nil
sender"
self assert: nextContext method selector = #cannotReturn:!
Hi Jaromir,
On 2024-01-03T22:42:12+00:00, mail@jaromir.net wrote:
Hi Christoph,
On 02-Jan-24 8:10:55 PM, christoph.thiede(a)student.hpi.uni-potsdam.de wrote:
+1 provided that no one objects against this breaking change after a couple of days (see https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...).
And you omitted two chances for #assert:equals: again. But maybe that's a style questions only. After all, we are obfuscating our tests and testing framework by duplicating basic protocols from the rest of the systems, for the sole purpose of generating better assertion error messages. :-) I agree with Eliot when he suggested a couple of years ago to use metaprogramming for generating these messages instead (I can try to find that thread again when you're interested).
Yes please, if you don't mind. Thanks!
Here you are: https://lists.squeakfoundation.org/archives/list/squeak-dev@lists.squeakfoun... Most of the thread revolves around better assertion concepts, but I have linked to the particular message in which I described my vision based on blocks and metaprogramming. I guess the issue of side effects when reevaluating assertion blocks could be solved by using a SimulationStudio Sandbox. :-)
Best, Christoph
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
On 2024-01-02T11:28:09+00:00, commits(a)source.squeak.org wrote:
A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil contexts
=============== Diff against KernelTests-jar.448 ===============
Item was added:
- ----- Method: ContextTest>>testBlockCannotReturnToNil (in category
'tests') -----
- testBlockCannotReturnToNil
- "Test if #return:from: correctly handles returns to dead or nil
contexts."
- | context nextContext |
- context := [] asContext.
- "assert p is at the last instruction, i.e. a return, and is
about to return to a nil context"
- self assert: context method selector = thisContext method
selector.
- self assert: context sender isNil.
- self assert: context willReturn.
- self assert: context atEnd.
- nextContext := context step. "step into a return to a nil
sender"
- self assert: nextContext method selector = #cannotReturn:!
--- Sent from Squeak Inbox Talk
Hi Christoph,
Exactly - both issues have been bothering me too :))
1. The order of #assert: expected equals: actual
I understand your concern re readability of convoluted asserts but most of them are simple and then the English order is definitely more readable.
As backward compatibility is an issue here I wouldn't mind adding sibling methods like e.g.
should: actual equal: expected
^ self assert: expected equals: actual description: nil
reversing the order. (or #assert: actual answers: expected, etc)
2. The ability to move tests to and from the Workspace
Being able to bind self to an object of your choice sounds really attractive (not that I know how to do that or what challenges it brings). Funny, I never realized using the Inspector's evaluator field is such a simple workaround - thanks for bringing this thread up!
Alas, I can't comment on your metaprogramming vision but it sounds like a quite complex exercise (likely due to my lack of tools and experience though ;) ).
Best! Jaromir
On 04-Jan-24 12:47:16 AM, christoph.thiede@student.hpi.uni-potsdam.de wrote:
Hi Jaromir,
On 2024-01-03T22:42:12+00:00, mail@jaromir.net wrote:
Hi Christoph,
On 02-Jan-24 8:10:55 PM,
christoph.thiede(a)student.hpi.uni-potsdam.de
wrote:
+1 provided that no one objects against this breaking change after a couple of days (see
https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...).
And you omitted two chances for #assert:equals: again. But maybe
that's
a style questions only. After all, we are obfuscating our tests and testing framework by duplicating basic protocols from the rest of
the
systems, for the sole purpose of generating better assertion error messages. :-) I agree with Eliot when he suggested a couple of years ago to use metaprogramming for generating these messages instead (I
can
try to find that thread again when you're interested).
Yes please, if you don't mind. Thanks!
Here you are: https://lists.squeakfoundation.org/archives/list/squeak-dev@lists.squeakfoun... Most of the thread revolves around better assertion concepts, but I have linked to the particular message in which I described my vision based on blocks and metaprogramming. I guess the issue of side effects when reevaluating assertion blocks could be solved by using a SimulationStudio Sandbox. :-)
Best, Christoph
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
On 2024-01-02T11:28:09+00:00, commits(a)source.squeak.org wrote:
A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil contexts
=============== Diff against KernelTests-jar.448 ===============
Item was added:
- ----- Method: ContextTest>>testBlockCannotReturnToNil (in
category
'tests') -----
- testBlockCannotReturnToNil
- "Test if #return:from: correctly handles returns to dead or nil
contexts."
- | context nextContext |
- context := [] asContext.
- "assert p is at the last instruction, i.e. a return, and is
about to return to a nil context"
- self assert: context method selector = thisContext method
selector.
- self assert: context sender isNil.
- self assert: context willReturn.
- self assert: context atEnd.
- nextContext := context step. "step into a return to a nil
sender"
- self assert: nextContext method selector = #cannotReturn:!
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
Hi Jaromir,
On 2024-01-04T18:39:30+00:00, mail@jaromir.net wrote:
Hi Christoph,
Exactly - both issues have been bothering me too :))
- The order of #assert: expected equals: actual
I understand your concern re readability of convoluted asserts but most of them are simple and then the English order is definitely more readable.
Philosophy! :-) Instead of 'self assert: expected equals: actual' vs 'self assert: actual equals: expected', let's talk about 'expected = actual' vs 'actual = expected'. Who is observing whom? Whom do you ask to do something? Assuming equality comparison is just a special case of validation, a general form might be 'expector accepts: actual' vs 'actual matches: expector'. I have a slight tendency to say the former is more idiomatic ... Just like String>>#match: vs. String>>#matchesRegex:, but the latter is only for conveience ... or not? More practically, let's also consider cases where #= is not symmetric (commutative): e.g., aString = aText ~= (aText = aString). So, actualSourceTextInBrowserThatIsAccidentallyAlsoStyled = expectedSourceStringWithoutStyling would evaluate to true but the opposite would not ... well, that gives a point for your position. :-)
Finally, what is the logical reading order? Does it only relate to the grammar of the isolated sentence/statement of the assertion? Or should it adhere to the general arrange-act-assert pattern (https://wiki.c2.com/?ArrangeActAssert)? In this case, it depends on whether you view the construction of the expected value as part of the arrange or assert stage ... I guess another reason why I prefer expected = equal is that when you insert a large expression for actual, the expectation is too far distant for me from the assert, making it hard to connect them for me:
self assert: "<-----------------------------------------------------------------------------------------------|" (self transformResult: "|" (self "|" doSomethingWith: self arrangeFirstArgument "|" and: self arrangeSecondArgument)) "|" equals: "|" expected. "wait, where does this belong to? ---------oh.-------------------------|"
Where on the other hand, I have fewer trouble reading the following:
self assert: expected equals: "alright, that's what we're going to find out, now only the actual logic follows:" (self transformResult: (self doSomethingWith: self arrangeFirstArgument and: self arrangeSecondArgument)).
But in the end I think this is highly opinionated and depends on your habits.
As backward compatibility is an issue here I wouldn't mind adding sibling methods like e.g.
should: actual equal: expected
^ self assert: expected equals: actual description: nil
reversing the order. (or #assert: actual answers: expected, etc)
TBH I think that would mainly make the overall protocol on TestCase redundant and less clear. Just like the ambiguity between #fold: and #reduce: Unless we actually "soft-deprecated" #assert:equals:, which would still result in a lot of inconsistent tests. If we were to invent a new testing framework, I might agree with you (but still not sure ^^) (or more likely, not introduce any convenience assertion selectors at all, see below), but for an existing and well-established framework, I do not think this is a good chance. Too much noise for too little added benefit. IMHO. :-)
- The ability to move tests to and from the Workspace
Being able to bind self to an object of your choice sounds really attractive (not that I know how to do that or what challenges it brings). Funny, I never realized using the Inspector's evaluator field is such a simple workaround - thanks for bringing this thread up!
Or also consider the other proposal I mentioned somewhere - allow workspace variables in inspectors, too. One possibly significant UX problem that I could imagine with both proposals is the missing visibility/discoverability of such bindings: how many GB does this workspace/inspector hold? Will I loose any objects when I close that window? And here is another one: does this variable which is styled in black refer to an instance variable of the receiver or to a workspace variable? Also, workspace variables are not available in the debugger - it should be possible to scan all bytecodes of the current context to find them, but might slow things down and bloats the mental model. Maybe we could also supersede the entire concept of workspace variables and make the receiver of every workspace a new uniclass object instead, where every assignment to an unknown variable will create a new instance variable instead. So many possibilities ... :-)
Alas, I can't comment on your metaprogramming vision but it sounds like a quite complex exercise (likely due to my lack of tools and experience though ;) ).
I don't know for sure! Here would be another approach that is robust against side-effects: Try to match the assertion block against simple patterns such as (...) = (...). If a pattern is found, evaluate the arguments separately (be sure to maintain the original evaluation order), remember their results, then evaluate the remaining pattern. Pattern detection could either work by decompilng the AST or using the bytecode. AST might be easier to scan, but bytecode is easier to evaluate step-by-step using the simulator. Both are slower than evaluating the block directly. But right now the latter sounds more attractive to me. For the beginning, we could just check whether the penultimate instruction is a #= send and if yes, replace it by a #sunitReasonWhyNotEquals: send. It gets more complicated if we want to provide friendly assertion messages for complex conditionals and branches in assertion blocks as well ...
Best! Jaromir
On 04-Jan-24 12:47:16 AM, christoph.thiede(a)student.hpi.uni-potsdam.de wrote:
Hi Jaromir,
On 2024-01-03T22:42:12+00:00, mail(a)jaromir.net wrote:
Hi Christoph,
On 02-Jan-24 8:10:55 PM,
christoph.thiede(a)student.hpi.uni-potsdam.de
wrote:
+1 provided that no one objects against this breaking change after a couple of days (see
https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...).
And you omitted two chances for #assert:equals: again. But maybe
that's
a style questions only. After all, we are obfuscating our tests and testing framework by duplicating basic protocols from the rest of
the
systems, for the sole purpose of generating better assertion error messages. :-) I agree with Eliot when he suggested a couple of years ago to use metaprogramming for generating these messages instead (I
can
try to find that thread again when you're interested).
Yes please, if you don't mind. Thanks!
Here you are: https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo... Most of the thread revolves around better assertion concepts, but I have linked to the particular message in which I described my vision based on blocks and metaprogramming. I guess the issue of side effects when reevaluating assertion blocks could be solved by using a SimulationStudio Sandbox. :-)
Best, Christoph
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
On 2024-01-02T11:28:09+00:00, commits(a)source.squeak.org wrote:
A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil contexts
=============== Diff against KernelTests-jar.448 ===============
Item was added:
- ----- Method: ContextTest>>testBlockCannotReturnToNil (in
category
'tests') -----
- testBlockCannotReturnToNil
- "Test if #return:from: correctly handles returns to dead or nil
contexts."
- | context nextContext |
- context := [] asContext.
- "assert p is at the last instruction, i.e. a return, and is
about to return to a nil context"
- self assert: context method selector = thisContext method
selector.
- self assert: context sender isNil.
- self assert: context willReturn.
- self assert: context atEnd.
- nextContext := context step. "step into a return to a nil
sender"
- self assert: nextContext method selector = #cannotReturn:!
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
Best, Christoph
--- Sent from Squeak Inbox Talk
Hi Christoph, Thanks for interesting arguments!
On 06-Jan-24 9:31:58 PM, christoph.thiede@student.hpi.uni-potsdam.de wrote:
Hi Jaromir,
On 2024-01-04T18:39:30+00:00, mail@jaromir.net wrote:
Hi Christoph,
Exactly - both issues have been bothering me too :))
- The order of #assert: expected equals: actual
I understand your concern re readability of convoluted asserts but
most
of them are simple and then the English order is definitely more readable.
Philosophy! :-) Instead of 'self assert: expected equals: actual' vs 'self assert: actual equals: expected', let's talk about 'expected = actual' vs 'actual = expected'. Who is observing whom? Whom do you ask to do something?
Exactly - but I don't think it's object's responsibilty to validate itself's equality with some other object. We have an independent validator, a TestCase, that does that... like a notary ;) And thus I prefer English notation (assuming the English notary) to communicate the case. Plus, simplified English equalled to Smalltalk's syntax often is ;)
Assuming equality comparison is just a special case of validation, a general form might be 'expector accepts: actual' vs 'actual matches: expector'. I have a slight tendency to say the former is more idiomatic ... Just like String>>#match: vs. String>>#matchesRegex:, but the latter is only for conveience ... or not? More practically, let's also consider cases where #= is not symmetric (commutative): e.g., aString = aText ~= (aText = aString).
Equality that is not commutative or transitive is an aberration, ugh! :)
So, actualSourceTextInBrowserThatIsAccidentallyAlsoStyled = expectedSourceStringWithoutStyling would evaluate to true but the opposite would not ... well, that gives a point for your position. :-)
Finally, what is the logical reading order? Does it only relate to the grammar of the isolated sentence/statement of the assertion? Or should it adhere to the general arrange-act-assert pattern (https://wiki.c2.com/?ArrangeActAssert)? In this case, it depends on whether you view the construction of the expected value as part of the arrange or assert stage ... I guess another reason why I prefer expected = equal is that when you insert a large expression for actual, the expectation is too far distant for me from the assert, making it hard to connect them for me:
Yes, a good argument; I guess the same one may have been applied when Smalltalk founders decided to give assignment the form `var <- value` rather than `value -> var` ;)
self
assert:"<-----------------------------------------------------------------------------------------------|" (selftransformResult:"|" (self"|" doSomethingWith:selfarrangeFirstArgument"|" and:selfarrangeSecondArgument))"|" equals:"|" expected."wait, where does this belong to? ---------oh.-------------------------|"
Where on the other hand, I have fewer trouble reading the following:
selfassert:expectedequals:"alright, that's what we're going to find out, now only the actual logic follows:" (selftransformResult: (self doSomethingWith:selfarrangeFirstArgument and:selfarrangeSecondArgument)).
But in the end I think this is highly opinionated and depends on your habits.
As backward compatibility is an issue here I wouldn't mind adding sibling methods like e.g.
should: actual equal: expected
^ self assert: expected equals: actual description: nil
reversing the order. (or #assert: actual answers: expected, etc)
TBH I think that would mainly make the overall protocol on TestCase redundant and less clear. Just like the ambiguity between #fold: and #reduce:
Probably right... btw. throw #inject:into: into the mix. It's called `fold` in some languages :)
Unless we actually "soft-deprecated" #assert:equals:, which would still result in a lot of inconsistent tests. If we were to invent a new testing framework, I might agree with you (but still not sure ^^) (or more likely, not introduce any convenience assertion selectors at all, see below), but for an existing and well-established framework, I do not think this is a good chance. Too much noise for too little added benefit. IMHO. :-)
- The ability to move tests to and from the Workspace
Being able to bind self to an object of your choice sounds really attractive (not that I know how to do that or what challenges it brings). Funny, I never realized using the Inspector's evaluator
field
is such a simple workaround - thanks for bringing this thread up!
Or also consider the other proposal I mentioned somewhere - allow workspace variables in inspectors, too. One possibly significant UX problem that I could imagine with both proposals is the missing visibility/discoverability of such bindings: how many GB does this workspace/inspector hold? Will I loose any objects when I close that window? And here is another one: does this variable which is styled in black refer to an instance variable of the receiver or to a workspace variable? Also, workspace variables are not available in the debugger - it should be possible to scan all bytecodes of the current context to find them, but might slow things down and bloats the mental model. Maybe we could also supersede the entire concept of workspace variables and make the receiver of every workspace a new uniclass object instead, where every assignment to an unknown variable will create a new instance variable instead. So many possibilities ... :-)
Then perhaps "hardcode" just one alternative TestWorkspace tool binding self to a TestCase instance - as a convenience/reminder only, really, because when you realize you can use the Inspector, it's no longer a big deal.
Alas, I can't comment on your metaprogramming vision but it sounds
like
a quite complex exercise (likely due to my lack of tools and
experience
though ;) ).
I don't know for sure! Here would be another approach that is robust against side-effects: Try to match the assertion block against simple patterns such as (...) = (...). If a pattern is found, evaluate the arguments separately (be sure to maintain the original evaluation order), remember their results, then evaluate the remaining pattern. Pattern detection could either work by decompilng the AST or using the bytecode. AST might be easier to scan, but bytecode is easier to evaluate step-by-step using the simulator. Both are slower than evaluating the block directly. But right now the latter sounds more attractive to me. For the beginning, we could just check whether the penultimate instruction is a #= send and if yes, replace it by a #sunitReasonWhyNotEquals: send. It gets more complicated if we want to provide friendly assertion messages for complex conditionals and branches in assertion blocks as well ...
Best! Jaromir
On 04-Jan-24 12:47:16 AM,
christoph.thiede(a)student.hpi.uni-potsdam.de
wrote:
Hi Jaromir,
On 2024-01-03T22:42:12+00:00, mail(a)jaromir.net wrote:
Hi Christoph,
On 02-Jan-24 8:10:55 PM,
christoph.thiede(a)student.hpi.uni-potsdam.de
wrote:
+1 provided that no one objects against this breaking change
after a
couple of days (see
https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...).
And you omitted two chances for #assert:equals: again. But maybe
that's
a style questions only. After all, we are obfuscating our tests
and
testing framework by duplicating basic protocols from the rest
of
the
systems, for the sole purpose of generating better assertion
error
messages. :-) I agree with Eliot when he suggested a couple of
years
ago to use metaprogramming for generating these messages instead
(I
can
try to find that thread again when you're interested).
Yes please, if you don't mind. Thanks!
Here you are:
https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...
Most of the thread revolves around better assertion concepts, but I have linked to the particular message in which I described my vision based on blocks and metaprogramming. I guess the issue of side
effects
when reevaluating assertion blocks could be solved by using a SimulationStudio Sandbox. :-)
Best, Christoph
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
On 2024-01-02T11:28:09+00:00, commits(a)source.squeak.org wrote:
A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.449.mcz
==================== Summary ====================
Name: KernelTests-jar.449 Author: jar Time: 2 January 2024, 12:28:08.184411 pm UUID: decf5a85-87ad-5849-b692-ee28940eab41 Ancestors: KernelTests-jar.448
Test if #return:from: correctly handles returns to nil
contexts
=============== Diff against KernelTests-jar.448
===============
Item was added:
- ----- Method: ContextTest>>testBlockCannotReturnToNil (in
category
'tests') -----
- testBlockCannotReturnToNil
- "Test if #return:from: correctly handles returns to dead or
nil
contexts."
- | context nextContext |
- context := [] asContext.
- "assert p is at the last instruction, i.e. a return, and is
about to return to a nil context"
- self assert: context method selector = thisContext method
selector.
- self assert: context sender isNil.
- self assert: context willReturn.
- self assert: context atEnd.
- nextContext := context step. "step into a return to a nil
sender"
- self assert: nextContext method selector = #cannotReturn:!
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
Hi Jaromir,
On 2024-01-06T23:07:57+00:00, mail@jaromir.net wrote:
Hi Christoph, Thanks for interesting arguments!
On 06-Jan-24 9:31:58 PM, christoph.thiede(a)student.hpi.uni-potsdam.de wrote:
Hi Jaromir,
On 2024-01-04T18:39:30+00:00, mail(a)jaromir.net wrote:
Hi Christoph,
Exactly - both issues have been bothering me too :))
- The order of #assert: expected equals: actual
I understand your concern re readability of convoluted asserts but
most
of them are simple and then the English order is definitely more readable.
Philosophy! :-) Instead of 'self assert: expected equals: actual' vs 'self assert: actual equals: expected', let's talk about 'expected = actual' vs 'actual = expected'. Who is observing whom? Whom do you ask to do something?
Exactly - but I don't think it's object's responsibilty to validate itself's equality with some other object. We have an independent validator, a TestCase, that does that... like a notary ;)
Fair point! But this bloats up the vocabulary of TestCase again then. I don't want #assert:greaterThan: or #assert:matchesRegex: or #assertPoint:isInsideRectangle: on TestCase. It does not add value but duplication, and if we only have #assert:equals:, it's inconsistent to assert: [a closeTo: b] etc. So, I would say, the "notary" is involved enough by sending it the message #assert:.
And thus I prefer English notation (assuming the English notary) to communicate the case. Plus, simplified English equalled to Smalltalk's syntax often is ;)
Assuming equality comparison is just a special case of validation, a general form might be 'expector accepts: actual' vs 'actual matches: expector'. I have a slight tendency to say the former is more idiomatic ... Just like String>>#match: vs. String>>#matchesRegex:, but the latter is only for conveience ... or not? More practically, let's also consider cases where #= is not symmetric (commutative): e.g., aString = aText ~= (aText = aString).
Equality that is not commutative or transitive is an aberration, ugh! :)
Agreed!
So, actualSourceTextInBrowserThatIsAccidentallyAlsoStyled = expectedSourceStringWithoutStyling would evaluate to true but the opposite would not ... well, that gives a point for your position. :-)
Finally, what is the logical reading order? Does it only relate to the grammar of the isolated sentence/statement of the assertion? Or should it adhere to the general arrange-act-assert pattern (https://wiki.c2.com/?ArrangeActAssert)? In this case, it depends on whether you view the construction of the expected value as part of the arrange or assert stage ... I guess another reason why I prefer expected = equal is that when you insert a large expression for actual, the expectation is too far distant for me from the assert, making it hard to connect them for me:
Yes, a good argument; I guess the same one may have been applied when Smalltalk founders decided to give assignment the form `var <- value` rather than `value -> var` ;)
self
assert:"<-----------------------------------------------------------------------------------------------|" (selftransformResult:"|" (self"|" doSomethingWith:selfarrangeFirstArgument"|" and:selfarrangeSecondArgument))"|" equals:"|" expected."wait, where does this belong to? ---------oh.-------------------------|"
Where on the other hand, I have fewer trouble reading the following:
selfassert:expectedequals:"alright, that's what we're going to find out, now only the actual logic follows:" (selftransformResult: (self doSomethingWith:selfarrangeFirstArgument and:selfarrangeSecondArgument)).
But in the end I think this is highly opinionated and depends on your habits.
As backward compatibility is an issue here I wouldn't mind adding sibling methods like e.g.
should: actual equal: expected
^ self assert: expected equals: actual description: nil
reversing the order. (or #assert: actual answers: expected, etc)
TBH I think that would mainly make the overall protocol on TestCase redundant and less clear. Just like the ambiguity between #fold: and #reduce:
Probably right... btw. throw #inject:into: into the mix. It's called `fold` in some languages :)
Unless we actually "soft-deprecated" #assert:equals:, which would still result in a lot of inconsistent tests. If we were to invent a new testing framework, I might agree with you (but still not sure ^^) (or more likely, not introduce any convenience assertion selectors at all, see below), but for an existing and well-established framework, I do not think this is a good chance. Too much noise for too little added benefit. IMHO. :-)
- The ability to move tests to and from the Workspace
Being able to bind self to an object of your choice sounds really attractive (not that I know how to do that or what challenges it brings). Funny, I never realized using the Inspector's evaluator
field
is such a simple workaround - thanks for bringing this thread up!
Or also consider the other proposal I mentioned somewhere - allow workspace variables in inspectors, too. One possibly significant UX problem that I could imagine with both proposals is the missing visibility/discoverability of such bindings: how many GB does this workspace/inspector hold? Will I loose any objects when I close that window? And here is another one: does this variable which is styled in black refer to an instance variable of the receiver or to a workspace variable? Also, workspace variables are not available in the debugger - it should be possible to scan all bytecodes of the current context to find them, but might slow things down and bloats the mental model. Maybe we could also supersede the entire concept of workspace variables and make the receiver of every workspace a new uniclass object instead, where every assignment to an unknown variable will create a new instance variable instead. So many possibilities ... :-)
Then perhaps "hardcode" just one alternative TestWorkspace tool binding self to a TestCase instance - as a convenience/reminder only, really, because when you realize you can use the Inspector, it's no longer a big deal.
Alas, I can't comment on your metaprogramming vision but it sounds
like
a quite complex exercise (likely due to my lack of tools and
experience
though ;) ).
I don't know for sure! Here would be another approach that is robust against side-effects: Try to match the assertion block against simple patterns such as (...) = (...). If a pattern is found, evaluate the arguments separately (be sure to maintain the original evaluation order), remember their results, then evaluate the remaining pattern. Pattern detection could either work by decompilng the AST or using the bytecode. AST might be easier to scan, but bytecode is easier to evaluate step-by-step using the simulator. Both are slower than evaluating the block directly. But right now the latter sounds more attractive to me. For the beginning, we could just check whether the penultimate instruction is a #= send and if yes, replace it by a #sunitReasonWhyNotEquals: send. It gets more complicated if we want to provide friendly assertion messages for complex conditionals and branches in assertion blocks as well ...
Best! Jaromir
On 04-Jan-24 12:47:16 AM,
christoph.thiede(a)student.hpi.uni-potsdam.de
wrote:
Hi Jaromir,
On 2024-01-03T22:42:12+00:00, mail(a)jaromir.net wrote:
Hi Christoph,
On 02-Jan-24 8:10:55 PM,
christoph.thiede(a)student.hpi.uni-potsdam.de
wrote:
+1 provided that no one objects against this breaking change
after a
couple of days (see
https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...).
And you omitted two chances for #assert:equals: again. But maybe
that's
a style questions only. After all, we are obfuscating our tests
and
testing framework by duplicating basic protocols from the rest
of
the
systems, for the sole purpose of generating better assertion
error
messages. :-) I agree with Eliot when he suggested a couple of
years
ago to use metaprogramming for generating these messages instead
(I
can
try to find that thread again when you're interested).
Yes please, if you don't mind. Thanks!
Here you are:
https://lists.squeakfoundation.org/archives/list/squeak-dev(a)lists.squeakfo...
Most of the thread revolves around better assertion concepts, but I have linked to the particular message in which I described my vision based on blocks and metaprogramming. I guess the issue of side
effects
when reevaluating assertion blocks could be solved by using a SimulationStudio Sandbox. :-)
Best, Christoph
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
On 2024-01-02T11:28:09+00:00, commits(a)source.squeak.org wrote:
> A new version of KernelTests was added to project The Inbox: > http://source.squeak.org/inbox/KernelTests-jar.449.mcz > > ==================== Summary ==================== > > Name: KernelTests-jar.449 > Author: jar > Time: 2 January 2024, 12:28:08.184411 pm > UUID: decf5a85-87ad-5849-b692-ee28940eab41 > Ancestors: KernelTests-jar.448 > > Test if #return:from: correctly handles returns to nil
contexts
> > =============== Diff against KernelTests-jar.448
===============
> > Item was added: > + ----- Method: ContextTest>>testBlockCannotReturnToNil (in
category
'tests') ----- > + testBlockCannotReturnToNil > + "Test if #return:from: correctly handles returns to dead or
nil
contexts." > + > + | context nextContext | > + context := [] asContext. > + > + "assert p is at the last instruction, i.e. a return, and is about to return to a nil context" > + self assert: context method selector = thisContext method selector. > + self assert: context sender isNil. > + self assert: context willReturn. > + self assert: context atEnd. > + > + nextContext := context step. "step into a return to a nil sender" > + > + self assert: nextContext method selector = #cannotReturn:!
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
--- Sent from Squeak Inbox Talk
squeak-dev@lists.squeakfoundation.org