assert:equals: in Object

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

assert:equals: in Object

Eliot Miranda-2
Hi All,

    moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it as being too green or ill considered or some other depressing BS.
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

marcel.taeumel
Hi Eliot,

sure, SUnit could put those extensions into Object. I wouldn't want to have those outside SUnit, though. Not sure why. I only consider #assert: a useful tool even outside test cases. Just to document an invariant in a method.

Best,
Marcel

Am 09.10.2020 10:24:58 schrieb Eliot Miranda <[hidden email]>:

Hi All,

    moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it as being too green or ill considered or some other depressing BS.
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Christoph Thiede

Hi Eliot, Hi Marcel,


-1 from my side for this change. :-)


If we start adding #assert:equals: and #assert:equals:description: on Object, it will be only a question of time until we will also discuss #deny:, #should:raise:, and all the other assertion selectors an object. And because it's not every object's purpose to provide such testing mechanisms, this feels like a step in the wrong direction for me. Object is bloated enough already. Instead of defining new assertion selectors (which happens for the single purpose of improving exception messages as I suppose), we should rather inspect the stack of an AssertionFailure/TestFailure to generate precise error messages.


Also, I am against defining these methods as extension methods because I would bet that someone (for example myself) would misinterpret them and assume they are part of the usual Object protocol, and suddenly you have a bunch of new dependencies from production code to SUnit.


Instead, we might miss some proper tooling for your use case, Eliot. Why can't we exchange the class of a Workspace's receiver? Or thinking differently, why can't we support dynamic workspace bindings in every inspector (maybe opt-in)? Then you could just inspect TestCase new, maximize the evaluator pane in the inspector, and e voilá you have a TestCase workspace.


Here are some references that might be related to this issue in some way:

http://forum.world.st/Modifying-a-method-s-bytecodes-is-it-supported-tp5114421p5114435.html (proposal for Workspace variables)

http://forum.world.st/The-Inbox-SUnit-ct-127-mcz-td5114709.html (about the addition of new assertion selectors)


Best,

Christoph






Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 9. Oktober 2020 11:41:26
An: squeak-dev
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Hi Eliot,

sure, SUnit could put those extensions into Object. I wouldn't want to have those outside SUnit, though. Not sure why. I only consider #assert: a useful tool even outside test cases. Just to document an invariant in a method.

Best,
Marcel

Am 09.10.2020 10:24:58 schrieb Eliot Miranda <[hidden email]>:

Hi All,

    moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it as being too green or ill considered or some other depressing BS.
_,,,^..^,,,_
best, Eliot


Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

marcel.taeumel
Hi Christoph,

still, it would be a shame if we would remove #assert:(description:) from Object, too. Then we couldn't document invariants in code anymore. So many trade-offs! :-O

As you suggested, this could be better solved at the tool level. The "self" binding in workspaces has great potential. Bind it to an example test case, and this would work. :-)

Best,
Marcel

Am 09.10.2020 14:34:20 schrieb Thiede, Christoph <[hidden email]>:

Hi Eliot, Hi Marcel,


-1 from my side for this change. :-)


If we start adding #assert:equals: and #assert:equals:description: on Object, it will be only a question of time until we will also discuss #deny:, #should:raise:, and all the other assertion selectors an object. And because it's not every object's purpose to provide such testing mechanisms, this feels like a step in the wrong direction for me. Object is bloated enough already. Instead of defining new assertion selectors (which happens for the single purpose of improving exception messages as I suppose), we should rather inspect the stack of an AssertionFailure/TestFailure to generate precise error messages.


Also, I am against defining these methods as extension methods because I would bet that someone (for example myself) would misinterpret them and assume they are part of the usual Object protocol, and suddenly you have a bunch of new dependencies from production code to SUnit.


Instead, we might miss some proper tooling for your use case, Eliot. Why can't we exchange the class of a Workspace's receiver? Or thinking differently, why can't we support dynamic workspace bindings in every inspector (maybe opt-in)? Then you could just inspect TestCase new, maximize the evaluator pane in the inspector, and e voilá you have a TestCase workspace.


Here are some references that might be related to this issue in some way:

http://forum.world.st/Modifying-a-method-s-bytecodes-is-it-supported-tp5114421p5114435.html (proposal for Workspace variables)

http://forum.world.st/The-Inbox-SUnit-ct-127-mcz-td5114709.html (about the addition of new assertion selectors)


Best,

Christoph






Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 9. Oktober 2020 11:41:26
An: squeak-dev
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Hi Eliot,

sure, SUnit could put those extensions into Object. I wouldn't want to have those outside SUnit, though. Not sure why. I only consider #assert: a useful tool even outside test cases. Just to document an invariant in a method.

Best,
Marcel

Am 09.10.2020 10:24:58 schrieb Eliot Miranda <[hidden email]>:

Hi All,

    moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it as being too green or ill considered or some other depressing BS.
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Christoph Thiede

Hi Marcel,


still, it would be a shame if we would remove #assert:(description:) from Object, too. Then we couldn't document invariants in code anymore. So many trade-offs! :-O


Yes, I absolutely agree with that. Production assertions are a useful feature. But compared to SUnit, they are not meant to fail at any time, and if they fail, they should do so during development only, so I don't think we have to optimize the meaningfulness of AssertionFailure messages (as opposed to TestFailures. See https://github.com/hpi-swa/smalltalkCI/issues/478 :-)).

As you suggested, this could be better solved at the tool level. The "self" binding in workspaces has great potential. Bind it to an example test case, and this would work. :-)

I do indeed think there is much potential for new ideas (and this would finally show me a reason why variable bindings can be useful as an orthogonal concept to instance variables). But how can we avoid redundancy between inspectors and workspaces at this point? How do you think about supporting dynamic bindings in every inspector's evaluator pane via opt-in? Or maybe add an item into Inspector's window menu, "convert to Workspace"?

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 9. Oktober 2020 14:40:43
An: squeak-dev
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Hi Christoph,

still, it would be a shame if we would remove #assert:(description:) from Object, too. Then we couldn't document invariants in code anymore. So many trade-offs! :-O

As you suggested, this could be better solved at the tool level. The "self" binding in workspaces has great potential. Bind it to an example test case, and this would work. :-)

Best,
Marcel

Am 09.10.2020 14:34:20 schrieb Thiede, Christoph <[hidden email]>:

Hi Eliot, Hi Marcel,


-1 from my side for this change. :-)


If we start adding #assert:equals: and #assert:equals:description: on Object, it will be only a question of time until we will also discuss #deny:, #should:raise:, and all the other assertion selectors an object. And because it's not every object's purpose to provide such testing mechanisms, this feels like a step in the wrong direction for me. Object is bloated enough already. Instead of defining new assertion selectors (which happens for the single purpose of improving exception messages as I suppose), we should rather inspect the stack of an AssertionFailure/TestFailure to generate precise error messages.


Also, I am against defining these methods as extension methods because I would bet that someone (for example myself) would misinterpret them and assume they are part of the usual Object protocol, and suddenly you have a bunch of new dependencies from production code to SUnit.


Instead, we might miss some proper tooling for your use case, Eliot. Why can't we exchange the class of a Workspace's receiver? Or thinking differently, why can't we support dynamic workspace bindings in every inspector (maybe opt-in)? Then you could just inspect TestCase new, maximize the evaluator pane in the inspector, and e voilá you have a TestCase workspace.


Here are some references that might be related to this issue in some way:

http://forum.world.st/Modifying-a-method-s-bytecodes-is-it-supported-tp5114421p5114435.html (proposal for Workspace variables)

http://forum.world.st/The-Inbox-SUnit-ct-127-mcz-td5114709.html (about the addition of new assertion selectors)


Best,

Christoph






Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 9. Oktober 2020 11:41:26
An: squeak-dev
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Hi Eliot,

sure, SUnit could put those extensions into Object. I wouldn't want to have those outside SUnit, though. Not sure why. I only consider #assert: a useful tool even outside test cases. Just to document an invariant in a method.

Best,
Marcel

Am 09.10.2020 10:24:58 schrieb Eliot Miranda <[hidden email]>:

Hi All,

    moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it as being too green or ill considered or some other depressing BS.
_,,,^..^,,,_
best, Eliot


Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

marcel.taeumel
For starters, I would stick to the example Eliot just gave us. And not "dream away" too soon. ;-)

Best,
Marcel

Am 09.10.2020 15:13:34 schrieb Thiede, Christoph <[hidden email]>:

Hi Marcel,


still, it would be a shame if we would remove #assert:(description:) from Object, too. Then we couldn't document invariants in code anymore. So many trade-offs! :-O


Yes, I absolutely agree with that. Production assertions are a useful feature. But compared to SUnit, they are not meant to fail at any time, and if they fail, they should do so during development only, so I don't think we have to optimize the meaningfulness of AssertionFailure messages (as opposed to TestFailures. See https://github.com/hpi-swa/smalltalkCI/issues/478 :-)).

As you suggested, this could be better solved at the tool level. The "self" binding in workspaces has great potential. Bind it to an example test case, and this would work. :-)

I do indeed think there is much potential for new ideas (and this would finally show me a reason why variable bindings can be useful as an orthogonal concept to instance variables). But how can we avoid redundancy between inspectors and workspaces at this point? How do you think about supporting dynamic bindings in every inspector's evaluator pane via opt-in? Or maybe add an item into Inspector's window menu, "convert to Workspace"?

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 9. Oktober 2020 14:40:43
An: squeak-dev
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Hi Christoph,

still, it would be a shame if we would remove #assert:(description:) from Object, too. Then we couldn't document invariants in code anymore. So many trade-offs! :-O

As you suggested, this could be better solved at the tool level. The "self" binding in workspaces has great potential. Bind it to an example test case, and this would work. :-)

Best,
Marcel

Am 09.10.2020 14:34:20 schrieb Thiede, Christoph <[hidden email]>:

Hi Eliot, Hi Marcel,


-1 from my side for this change. :-)


If we start adding #assert:equals: and #assert:equals:description: on Object, it will be only a question of time until we will also discuss #deny:, #should:raise:, and all the other assertion selectors an object. And because it's not every object's purpose to provide such testing mechanisms, this feels like a step in the wrong direction for me. Object is bloated enough already. Instead of defining new assertion selectors (which happens for the single purpose of improving exception messages as I suppose), we should rather inspect the stack of an AssertionFailure/TestFailure to generate precise error messages.


Also, I am against defining these methods as extension methods because I would bet that someone (for example myself) would misinterpret them and assume they are part of the usual Object protocol, and suddenly you have a bunch of new dependencies from production code to SUnit.


Instead, we might miss some proper tooling for your use case, Eliot. Why can't we exchange the class of a Workspace's receiver? Or thinking differently, why can't we support dynamic workspace bindings in every inspector (maybe opt-in)? Then you could just inspect TestCase new, maximize the evaluator pane in the inspector, and e voilá you have a TestCase workspace.


Here are some references that might be related to this issue in some way:

http://forum.world.st/Modifying-a-method-s-bytecodes-is-it-supported-tp5114421p5114435.html (proposal for Workspace variables)

http://forum.world.st/The-Inbox-SUnit-ct-127-mcz-td5114709.html (about the addition of new assertion selectors)


Best,

Christoph






Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Freitag, 9. Oktober 2020 11:41:26
An: squeak-dev
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Hi Eliot,

sure, SUnit could put those extensions into Object. I wouldn't want to have those outside SUnit, though. Not sure why. I only consider #assert: a useful tool even outside test cases. Just to document an invariant in a method.

Best,
Marcel

Am 09.10.2020 10:24:58 schrieb Eliot Miranda <[hidden email]>:

Hi All,

    moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it as being too green or ill considered or some other depressing BS.
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Tony Garnock-Jones-5
In reply to this post by Christoph Thiede
On 10/9/20 2:34 PM, Thiede, Christoph wrote:
> Hi Eliot, Hi Marcel, -1 from my side for this change. :-)

Me too. I think it's almost a case of Gun>>draw vs Shape>>draw --
assert: in Object is for invariant-specification.

> Instead, we might miss some proper tooling for your use case, Eliot.
> Why can't we exchange the class of a Workspace's receiver?

I really like this line of thinking! I've been mulling over the idea of
having an ActorWorkspace that exists within the context of a running
Actor so it can react to events, "crash", etc. (It makes sense in
context -- Erlangish (and Syndicateish) actors are deeper participants
in their ecosystems than vanilla Actors are...)

Anyway, having it by default be the case that Workspaces' code
environments be TestCases seems very sensible to me.

I also wanted to respond to this:

> Production assertions are a useful feature. But compared to SUnit,
> they are not meant to fail at any time, and if they fail, they
> should do so during development only,

I wanted to make sure we are all on the same page by suggesting a
clarification here. I think, Christoph, that you *should* have meant :-)
something like:

"Assertions of invariants in production code [as opposed to just in
testing code] are useful. But they MUST BE LEFT ACTIVE IN PRODUCTION
CODE because otherwise it's like wearing a seatbelt only while you're on
your own driveway, and taking it off as soon as you're on the street."

Hopefully I'm right! :-)

It just alarmed me a bit to see discussion of making the same mistake C
makes, namely compiling away assertions in "release" builds, which is
where you need them most...

Cheers,
  Tony

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Christoph Thiede

Hi Tony,


Anyway, having it by default be the case that Workspaces' code environments be TestCases seems very sensible to me.


What do you mean by this? Such a TestCase receiver environment should definitively be not the default, this would be very confusing!

"Assertions of invariants in production code [as opposed to just in testing code] are useful. But they MUST BE LEFT ACTIVE IN PRODUCTION CODE because otherwise it's like wearing a seatbelt only while you're on your own driveway, and taking it off as soon as you're on the street."

Absolutely! All I wanted to avoid is that we introduce an SUnit extension on Object and no one notices that it is an extension method and then will misuse #assert:equals: as an assertion in production code - which would break his or her package if it is installed in another environment that misses the SUnit package. Are we on the same page now? :-)

Best,
Christoph

Von: Tony Garnock-Jones <[hidden email]>
Gesendet: Freitag, 9. Oktober 2020 16:33:12
An: The general-purpose Squeak developers list; Thiede, Christoph
Betreff: Re: [squeak-dev] assert:equals: in Object
 
On 10/9/20 2:34 PM, Thiede, Christoph wrote:
> Hi Eliot, Hi Marcel, -1 from my side for this change. :-)

Me too. I think it's almost a case of Gun>>draw vs Shape>>draw --
assert: in Object is for invariant-specification.

> Instead, we might miss some proper tooling for your use case, Eliot.
> Why can't we exchange the class of a Workspace's receiver?

I really like this line of thinking! I've been mulling over the idea of
having an ActorWorkspace that exists within the context of a running
Actor so it can react to events, "crash", etc. (It makes sense in
context -- Erlangish (and Syndicateish) actors are deeper participants
in their ecosystems than vanilla Actors are...)

Anyway, having it by default be the case that Workspaces' code
environments be TestCases seems very sensible to me.

I also wanted to respond to this:

> Production assertions are a useful feature. But compared to SUnit,
> they are not meant to fail at any time, and if they fail, they
> should do so during development only,

I wanted to make sure we are all on the same page by suggesting a
clarification here. I think, Christoph, that you *should* have meant :-)
something like:

"Assertions of invariants in production code [as opposed to just in
testing code] are useful. But they MUST BE LEFT ACTIVE IN PRODUCTION
CODE because otherwise it's like wearing a seatbelt only while you're on
your own driveway, and taking it off as soon as you're on the street."

Hopefully I'm right! :-)

It just alarmed me a bit to see discussion of making the same mistake C
makes, namely compiling away assertions in "release" builds, which is
where you need them most...

Cheers,
  Tony


Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Tony Garnock-Jones-5
Hi Christoph,

On 10/9/20 4:53 PM, Thiede, Christoph wrote:
>> Anyway, having it by default be the case that Workspaces'
> code environments be TestCases seems very sensible to me.
>
> What do you mean by this? Such a TestCase receiver environment should
> definitively be not the default, this would be very confusing!

Oh interesting! What kind of confusion do you foresee? I had just
imagined that the only visible-ish change would be availability of
TestCase instance-side methods on the "self" in the Workspace.

>> "Assertions [...] MUST BE LEFT ACTIVE IN
>> PRODUCTION CODE
>
> Are we on the same page now? :-)

Yes, I think we are! :-) Thanks.

Tony

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Levente Uzonyi
In reply to this post by Eliot Miranda-2
Hi Eliot,

On Fri, 9 Oct 2020, Eliot Miranda wrote:

> Hi All,
>
>     moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the
> equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it
> as being too green or ill considered or some other depressing BS.

In my opinion, it would be better to get rid of #assert:equals: and
#assert:equals:description:. Many find the order of its arguments
confusing, and they are only good to help tracking down what failed.
If #assert: could give information about it's argument: the source code
and probably the values of the variables in it, then #assert:equals: would
simply become unnecessary.

For example

| x y |
x := 'foo'.
y := 1.
self assert: x = y.

would signal an exception with the message 'Assertion failed: x = y (x =
''foo'', y = 1)' instead of just 'Assertion failed'.


Levente

> _,,,^..^,,,_
> best, Eliot
>
>

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Eliot Miranda-2
Hi Levente,

On Fri, Oct 9, 2020 at 4:04 PM Levente Uzonyi <[hidden email]> wrote:
Hi Eliot,

On Fri, 9 Oct 2020, Eliot Miranda wrote:

> Hi All,
>
>     moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the
> equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it
> as being too green or ill considered or some other depressing BS.

In my opinion, it would be better to get rid of #assert:equals: and
#assert:equals:description:. Many find the order of its arguments
confusing, and they are only good to help tracking down what failed.
If #assert: could give information about it's argument: the source code
and probably the values of the variables in it, then #assert:equals: would
simply become unnecessary.

I couldn't agree more.  I *hate* assert:equals: being, for me, the wrong way round.  We would need to provide an abstraction around extracting the parse tree for an argument, which shouldn't be too hard.  Let me take a look at this and see if I can provide something simple and robust.

For example

| x y |
x := 'foo'.
y := 1.
self assert: x = y.

would signal an exception with the message 'Assertion failed: x = y (x =
''foo'', y = 1)' instead of just 'Assertion failed'.


Levente

_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Eliot Miranda-2
Hi Levente,

On Mon, Oct 12, 2020 at 10:59 AM Eliot Miranda <[hidden email]> wrote:
Hi Levente,

On Fri, Oct 9, 2020 at 4:04 PM Levente Uzonyi <[hidden email]> wrote:
Hi Eliot,

On Fri, 9 Oct 2020, Eliot Miranda wrote:

> Hi All,
>
>     moving code from a test into a workspace and back is painful because Object does not implement assert:equals: or assert:equals:description: even though it implements assert:description:.  So one has to edit out the
> equals: moving to the workspace and edit it back in again on the way back.  I'd like to suggest implementing Object>>assert:equals: and Object>>assert:equals:description: but I won't, because someone is bound to criticise it
> as being too green or ill considered or some other depressing BS.

In my opinion, it would be better to get rid of #assert:equals: and
#assert:equals:description:. Many find the order of its arguments
confusing, and they are only good to help tracking down what failed.
If #assert: could give information about it's argument: the source code
and probably the values of the variables in it, then #assert:equals: would
simply become unnecessary.

I couldn't agree more.  I *hate* assert:equals: being, for me, the wrong way round.  We would need to provide an abstraction around extracting the parse tree for an argument, which shouldn't be too hard.  Let me take a look at this and see if I can provide something simple and robust.

For example

| x y |
x := 'foo'.
y := 1.
self assert: x = y.

would signal an exception with the message 'Assertion failed: x = y (x =
''foo'', y = 1)' instead of just 'Assertion failed'.

Having thought about it a bit the problem is more difficult than it appears.  If the form of an assert is
    self assert: exprA = exprB
then in general only the result of exprA = exprB is available. exprA and exprB may have only been evaluated on the stack and not bound to variables.  So no matter tha introspection makes it trivial to derive the parse node and present the text for the expression: 'exprA = exprB' there is no way to retrieve the values of either exprA or exprB because they have been consumed and replaced by the result of their comparison.  This is what assert:equals: does; it binds both the actual and expected values to the arguments of assert:equals: and then performs the comparison.  So, absent time reversal debugging machinery (which has costs and is unlikely to be attractive for general use in running test suites which are > 99% correct most of the time) we're stuck with assert:equals:.

So things to think about are perhaps
- a sibling of assert:equals: which takes its arguments in the opposite order
- appealing to the SUnit community to reverse the order of arguments to assert:equals:, plus a rewrite rule that reversed the obvious cases where the first argument is a literal constant.
- seeing if assert:equals: could infer the order of its arguments; this would require some analysis.  For how many assert:equals: cases can it easily be determined if one or other of the arguments is the expected?  How many cases are ambiguous?  Are any undecidable? etc...
- implementing "backwards in time" debugging for the Test Runner when one selects a failing or erroring case.  This might be no more than instrumenting the method to place breakpoints before comparisons whose results are consumed by assert: variants and running up until the break.  This could be somewhat analogous to toggle break on entry in that adding/removing the pre comparison breakpoints would be automatic.  And one might be able to do it by mapping comparisons to comparisons for asserts.  e.g.  consider:

        self assert: a = b   (along with >, <, >= et al)
transformed into
        self assert: (a compareEqualForAssert: b)
where compareEqualForAssert: answers a structured object (AssertResult?) holding onto a, b, and the result of the comparison.  AssertResult would answer its result in response to value.  So assert methods (that already send value to coerce blocks and booleans to booleans) could send value to the argument, and then if that was false, query to see if the argument was an AssertResult and xtract a more informative error message if so.

All this is fun, and could function in the context of SUnit.  It does nothing to answer my problem of running asserts in Workspaces.  However, that was thoughtless on my part.  All I have to remember to do is inspect an instance of a TestCase class and evaluate my doit in that inspector.  So for the SocketTesxts if I had had my wits about me I would have simply inspected SocketTest new and then could use ll of SUnit's assert machinery in a doit in the inspector.


Levente

_,,,^..^,,,_
best, Eliot

_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Jakob Reschke
Eliot Miranda-2 wrote
> - appealing to the SUnit community to reverse the order of arguments to
> assert:equals:, plus a rewrite rule that reversed the obvious cases where
> the first argument is a literal constant.

For what it is worth, Pharo has just swapped the parameters... which makes
all "portable" test cases awkward.



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Christoph Thiede

Hi all, hi Eliot,


> What do you mean by this? Such a TestCase receiver environment should definitively be not the default, this would be very confusing!

> Oh interesting! What kind of confusion do you foresee? I had just imagined that the only visible-ish change would be availability of TestCase instance-side methods on the "self" in the Workspace.

SUnit is just one of so many domains. Someone else might want to evaluate things in the context of Transcript (self showln: 'foo') or any other console host (name := self input: 'Your name?'. self output: 'Hello ' , name) etc. pp....

@AssertResults via reflection:

Highly interesting topic! I already had some thoughts about this last summer and I have an image containing some stubs for it. My basic idea was to pass only blocks to the #assert: method that can more easily be decompiled, reevaluated, and whatever you wish. One then could identify the receiver "X" of the last message from the assertion block "X y: Z" and transform this message send into "X assert: #y: with: {Z}", where #assert:with: would be implemented on Object and could dispatch the assertion selector to several extension methods. This would allow us, for example, to write
self assert: [myList noneSatisfy: [:ea | ea hasPlung]]
and TestCase >> #assert:, under the hood, would this transform into
self assert: [myList assert: #noneSatisfy: with: [:ea | ea even]]
and then, an extension method á la #assertNoneSatisfy: could be called from #assert:with: and instead of only signaling a generic AssertionFailure, we could see something like:

"No object in myList should satisfy [:ea | ea even], but 4 (at index 2) does satisfy."

As a plus, every package/framework developer could simply add support for customized AssertionFailures by overriding that #assert:with: and handling custom test selectors.
If we wanted to go one step further, we could even try to detect nested calls, e.g.:
self assert: [(myList anySatisfy: [:ea | ea hasPlung]]) and: [myList size even]]
"myList should satisfy myList size even but did not"
"myList should satisfy myList size even but size is 5"

Ha, what a dream! And it shouldn't be terribly complicated, too ... For more inspiration, take a look at FluentAssertions for C#. :-)
(If anyone asks: I never realized this projects because I did not know what to do if one of these parameters has side effects, e.g. when a block is called. Any ideas?)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Jakob Reschke <[hidden email]>
Gesendet: Montag, 12. Oktober 2020 21:27:48
An: [hidden email]
Betreff: Re: [squeak-dev] assert:equals: in Object
 
Eliot Miranda-2 wrote
> - appealing to the SUnit community to reverse the order of arguments to
> assert:equals:, plus a rewrite rule that reversed the obvious cases where
> the first argument is a literal constant.

For what it is worth, Pharo has just swapped the parameters... which makes
all "portable" test cases awkward.



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Eliot Miranda-2
In reply to this post by Jakob Reschke


On Mon, Oct 12, 2020 at 12:27 PM Jakob Reschke <[hidden email]> wrote:
Eliot Miranda-2 wrote
> - appealing to the SUnit community to reverse the order of arguments to
> assert:equals:, plus a rewrite rule that reversed the obvious cases where
> the first argument is a literal constant.

For what it is worth, Pharo has just swapped the parameters... which makes
all "portable" test cases awkward.

Then IMO we should follow suit.  For once I agree with them ;-)
--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Christoph Thiede

Then IMO we should follow suit.  For once I agree with them ;-)


Nooo ... :( I don't know their reasons, but inverting a long-existing convention from one day to another seems like a true nightmare to me. This would invalidate the semantics of every existing test case that was ever written for Squeak/Smalltalk.

Plus, IMHO it is often useful to order parameters by their complexity ascending (e.g., put blocks last) to provide a good writeability/readability of a message's senders. While the expected argument often is a constant, the actual argument mainly is the result of a possibly complex operation, e.g.:

self assert: 42 equals: (myComputer
    doComplexComputationWith: 6
    and: 7
    mode: #multiplyInt).

How would the opposite read like?

self assert: (myComputer
    doComplexComputationWith: 6
    and: 7
    mode: #multiplyInt) equals: 42.

IMO, much less comprehensible.

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Dienstag, 13. Oktober 2020 04:02:48
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] assert:equals: in Object
 


On Mon, Oct 12, 2020 at 12:27 PM Jakob Reschke <[hidden email]> wrote:
Eliot Miranda-2 wrote
> - appealing to the SUnit community to reverse the order of arguments to
> assert:equals:, plus a rewrite rule that reversed the obvious cases where
> the first argument is a literal constant.

For what it is worth, Pharo has just swapped the parameters... which makes
all "portable" test cases awkward.

Then IMO we should follow suit.  For once I agree with them ;-)
--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



--
_,,,^..^,,,_
best, Eliot


Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Hannes Hirzel
Hello

On 10/13/20, Thiede, Christoph
<[hidden email]> wrote:
>> Then IMO we should follow suit.  For once I agree with them ;-)
>
> Nooo ... :( I don't know their reasons, but inverting a long-existing
> convention from one day to another seems like a true nightmare to me.

If I understand correctly Pharo has swapped
     assert:equals: in TestCase
to
     equals:assert: in TestCase

Is this so?

If yes then the impact for changes is actually quite small for Squeak.
It means that in addition to


assert: expected equals: actual

        ^self
                assert: expected = actual
                description: [ self comparingStringBetween: expected and: actual ]


a method

equals: actual assert: expected

       ^assert: expected equals: actual

is also needed in Squeak.

> This would invalidate the semantics of every existing test case that was ever
> written for Squeak/Smalltalk.

Not the semantics which is the about the meaning. It is a minor syntax
change (= change of structure/ form): the order of arguments in one or
two methods.

So one or two methods more in Squeak fixes this.

> Plus, IMHO it is often useful to order parameters by their complexity
> ascending (e.g., put blocks last) to provide a good writeability/readability
> of a message's senders. While the expected argument often is a constant, the
> actual argument mainly is the result of a possibly complex operation, e.g.:
>
> self assert: 42 equals: (myComputer
>     doComplexComputationWith: 6
>     and: 7
>     mode: #multiplyInt).
>
> How would the opposite read like?
>
> self assert: (myComputer
>     doComplexComputationWith: 6
>     and: 7
>     mode: #multiplyInt) equals: 42.
>
> IMO, much less comprehensible.

I agree that the former

self assert: 42 equals: (myComputer
       doComplexComputationWith: 6
       and: 7
      mode: #multiplyInt).

is much more readable. This is what Squeak implements.

Best wishes
Hannes

> Best,
> Christoph
>
> ________________________________
> Von: Squeak-dev <[hidden email]> im Auftrag
> von Eliot Miranda <[hidden email]>
> Gesendet: Dienstag, 13. Oktober 2020 04:02:48
> An: The general-purpose Squeak developers list
> Betreff: Re: [squeak-dev] assert:equals: in Object
>
>
>
> On Mon, Oct 12, 2020 at 12:27 PM Jakob Reschke
> <[hidden email]<mailto:[hidden email]>> wrote:
> Eliot Miranda-2 wrote
>> - appealing to the SUnit community to reverse the order of arguments to
>> assert:equals:, plus a rewrite rule that reversed the obvious cases where
>> the first argument is a literal constant.
>
> For what it is worth, Pharo has just swapped the parameters... which makes
> all "portable" test cases awkward.
>
> Then IMO we should follow suit.  For once I agree with them ;-)
> --
> Sent from: http://forum.world.st/Squeak-Dev-f45488.html
>
>
>
> --
> _,,,^..^,,,_
> best, Eliot
>

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Jakob Reschke
Hannes Hirzel wrote
> If I understand correctly Pharo has swapped
>      assert:equals: in TestCase
> to
>      equals:assert: in TestCase
>
> Is this so?

Unfortunately, no.

From Pharo 6.1:

TAssertable>>assert: actual equals: expected
        ^ self
                assert: expected = actual
                description: [self comparingStringBetween: actual and: expected]



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

Hannes Hirzel
In reply to this post by Tony Garnock-Jones-5
On 10/9/20, Tony Garnock-Jones <[hidden email]> wrote:

> Hi Christoph,
>
> On 10/9/20 4:53 PM, Thiede, Christoph wrote:
>>> Anyway, having it by default be the case that Workspaces'
>> code environments be TestCases seems very sensible to me.
>>
>> What do you mean by this? Such a TestCase receiver environment should
>> definitively be not the default, this would be very confusing!
>
> Oh interesting! What kind of confusion do you foresee? I had just
> imagined that the only visible-ish change would be availability of
> TestCase instance-side methods on the "self" in the Workspace.
>
>>> "Assertions [...] MUST BE LEFT ACTIVE IN
>>> PRODUCTION CODE


>> Are we on the same page now? :-)
>
> Yes, I think we are! :-) Thanks.
>
> Tony

I consider that assertions are useful to have in the production code
an an argument in favor of having

      assert:equals:description:

implemented the class Object. A situation where SUnit and all the
tests are not necessarily loaded.

--Hannes

Reply | Threaded
Open this post in threaded view
|

Re: assert:equals: in Object

marcel.taeumel
A situation where SUnit and all the tests are not necessarily loaded.

Hmm... maybe we might consider adding an SUnit-Core? Well, not sure it makes sense to have an image without SUnit. But then you might want to also strip, e.g., network support to shrink the image file a little bit more. :-)

Best,
Marcel

Am 24.10.2020 13:01:30 schrieb H. Hirzel <[hidden email]>:

On 10/9/20, Tony Garnock-Jones wrote:
> Hi Christoph,
>
> On 10/9/20 4:53 PM, Thiede, Christoph wrote:
>>> Anyway, having it by default be the case that Workspaces'
>> code environments be TestCases seems very sensible to me.
>>
>> What do you mean by this? Such a TestCase receiver environment should
>> definitively be not the default, this would be very confusing!
>
> Oh interesting! What kind of confusion do you foresee? I had just
> imagined that the only visible-ish change would be availability of
> TestCase instance-side methods on the "self" in the Workspace.
>
>>> "Assertions [...] MUST BE LEFT ACTIVE IN
>>> PRODUCTION CODE


>> Are we on the same page now? :-)
>
> Yes, I think we are! :-) Thanks.
>
> Tony

I consider that assertions are useful to have in the production code
an an argument in favor of having

assert:equals:description:

implemented the class Object. A situation where SUnit and all the
tests are not necessarily loaded.

--Hannes



12