About TestCase >> assert:

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

Re: About TestCase >> assert:

Nicolas Cellier
However, would you really try to apply this kind of rule to the whole
Smalltalk Kernel ?
That would be interesting because these rules have a cost in
- speed
- readability of code
- extensibility of code

1) Speed: every little method calls a little method, calls a little method ...
At which level do you put the tests ?
How many times is the same test applied thru the call chain ?

2) Readability: 3 lines of assertions for two lines of code is too
much to my taste.
Opinions may vary...

3) Extensibility of code: you'll have to care not to restrict future
extensions too much.
Pushed to the limits, this ressembles static typing (fortunately we
shall use message isInteger rather than isKindOf: Integer).

I think Smalltalk quality is based on a completly different plane

Nicolas

2009/10/16 Stéphane Ducasse <[hidden email]>:

> Yes and this is really important because pre and post are valuable for
> software engineering quality
> promotion.
>
> Stef
>
> On Oct 16, 2009, at 1:55 AM, [hidden email] wrote:
>
>> Em 15/10/2009 04:50,  Stéphane Ducasse <[hidden email]>
>> escreveu:
>>
>> I see.  Eiffel ideas cross breeding Pharo Smalltalk!
>>
>>>
>>>    The idea  is that one day or  later we will have  to think about
>>>    the benefit  of pre  and post condition.   So assert:  in object
>>>    makes a lot of sense.
>>>
>>>    Now  indeed it  would be  good that  all the  tests  use assert:
>>>    without block and use should: for that case.
>>>
>>>    Stef On Oct 15, 2009, at 3:55 AM, [hidden email] wrote:
>>>
>>>> I don't either,  but I find strange the  complete hierarchy of
>>>> classes of  Pharo having  a method assert:  available. Perhaps
>>>> I'm blindfolded  and Pharo and  Squeak have found a  wider use
>>>> for assertions?
>>>
>>
>>
>>
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: About TestCase >> assert:

Stéphane Ducasse


> However, would you really try to apply this kind of rule to the whole
> Smalltalk Kernel ?
> That would be interesting because these rules have a cost in
> - speed
> - readability of code
> - extensibility of code
>
> 1) Speed: every little method calls a little method, calls a little  
> method ...
> At which level do you put the tests ?
> How many times is the same test applied thru the call chain ?

First preconditions in eiffel have different level of execution
you can completely disable them. Once the new compiler is in pharo and  
the default
compiler we could do really cool on the fly recompilation and have a  
large range of choices.

Then we can use preconditions to generate tests or as one of my friend  
did in eiffel and java
generate tests that you trash after and enhance the robustness of the  
preconditions.

I read the PhD of benoit baudry and once you read the conclusions and  
the results
it is clear that preconditions have really good properties. Now we  
have to be smart enough
to understand how we can take advantage of them in our setup.

> 2) Readability: 3 lines of assertions for two lines of code is too
> much to my taste.
> Opinions may vary...

It is a question of balance. Not everything is black or white.


> 3) Extensibility of code: you'll have to care not to restrict future
> extensions too much.
> Pushed to the limits, this ressembles static typing (fortunately we
> shall use message isInteger rather than isKindOf: Integer).

Again it is a question of balance and usage. We should decouple the  
tool from its usage.

I think that we should learn from it.

> I think Smalltalk quality is based on a completly different plane

You mean not checkable documentation, absence of documentation,
lack of static typing to document (because what would be good is to  
have a pluggable type system)




_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: About TestCase >> assert:

Mariano Martinez Peck
In reply to this post by Stéphane Ducasse


On Fri, Oct 16, 2009 at 4:45 AM, Stéphane Ducasse <[hidden email]> wrote:
> There are inconsistencies that bother me.
>
> * TestCase>>assert: in most Smalltalks accepts only a boolean. In
> Pharo,
> it accepts either a boolean or a block. This makes tests less
> portable.

+1

> * TestCase>>assert:equals: (a very useful method) does not accept a
> block. Anyone used to giving blocks to #assert: would probably expect
> this method to accept a block.

+1 consistency is nice.

> * Object assert: accepts a boolean or a block. I don't know of any
> standard for this.

me neither

> * BlockClosure>>assert does not take any arguments, so I feel it is
> very
> clean.

+1

> Proposed changes: (based on earlier discussion plus personal opinion)
>
> TestCase>>assert: should only accept a boolean. This brings
> compatibility with other Smalltalks, and consistency with
> TestCase>>assert:equals:.

+ 1

> Object>>assert: should be removed/deprecated in favor of
> BlockClosure>>assert. This removes confusion with TestCase>>assert:.

deprecation!

> Object>>assert:description: and Object>>assert:descriptionBlock:
> should
> be removed/deprecated in favor of (new)
> BlockClosure>>assertWithDescription:, which accepts either a block
> or a
> string. This provides convenient invariant and pre/post condition
> testing.

Let us do that.
Any taker?


I don't have time right now for this, but at least I created the ticket:

http://code.google.com/p/pharo/issues/detail?id=1329

Cheers,

mariano
 
Stef
>
>
> Opinions?
>
> -Martin
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: About TestCase >> assert:

Nicolas Cellier
In reply to this post by Stéphane Ducasse
2009/10/16 Stéphane Ducasse <[hidden email]>:
>
>> I think Smalltalk quality is based on a completly different plane
>

First, my reference about quality is not Squeak, I rather mean st-80
from ParcPlace :)
At least it used to have
- more generous class and method comments
- less bugs and obscure code (certainly because less code too !)
- a certain homogeneity (less programmers ?)

So were is the Smalltalk quality ?
- the ability to test code as soon as written
- the ability to write small and simple code,
- the ability to write readable code,
- the ability to extend code
Are these essential properties in the quality standards used in static typing ?

> You mean not checkable documentation, absence of documentation,
> lack of static typing to document (because what would be good is to
> have a pluggable type system)
>

I agree, lack of type can be seen as a weakness for documenting APIs.
As a workaround, we use funny parameter names (anArrayOfStrings).
Or we add a method comment (hem... at least we should).
I agree, all these comments will become false when code is changed,
and the quality will decrease...
As false as an outdated assertion... but silent... Maybe it's worse ?
Browsing senders, or inspecting the signature of message sent to, or
inserting a halt is sometimes our solutions...
I agree, this is not ideal.

So yes, assertions as a public declaration of API could be good for documenting.
And a good description of assertion failure can also provide
informative feedback to the user (more than a Debugger ?)

What I do not like is defensive assertions as a potential barrier to
extendability, because they correspond to a static view of code, a
snapshot of current state.
Smalltalk state does and will change. The image is living, and class
structure not written on stone.
Rapidly changing code is definitely not accepted as a quality standard...

In a rapidly changing image, assertions could be a supplementary drag
against change...
Suppose I have a method accepting a String parameter P: p.
    [p isString] assertWithDescription: 'method xxx only accept a
String as parameter P'.
Now maybe the method would have worked with a Text. I have been too restrictive:
    [p isCharacters] assertWithDescription: 'method xxx only accept characters'.
Now someone introduce WideString, and my code only work with ByteString.
    [p isCharacters and: [p asString isByteString]]
assertWithDescription: 'method xxx only accept byte characters'.
Yes, but the method does not work with empty String, I add:
    [p notEmpty] assertWithDescription: 'method xxx only accept non
empty strings'.
Nor does it with some control characters:
    self assertPHasValidCharacters: p.
Fortunately someone then correct the WideString case, now I can
retract isByteString.
Unfortunately, p will be stored in an inst. var. with many public interfaces...
Each time, I have to change all the false assertions in all senders of
the core method that are in the public API...
And maybe some of these public APIs are driven by other public APIs
(you meet this in Smalltalk, didn't you?)
To avoid this I create a specific method
assertPIsValid: p
    | sender |
    sender := thisContext sender homeContext selector.
    [p isCharacters] assertWithDescription: 'method ' , sender , '
only accept characters'.
    [p asString isByteString] assertWithDescription: 'method ' ,
sender , ' only accept byte characters'.
    [p notEmpty] assertWithDescription: 'method ' , sender , ' only
accept non empty strings'.
    self assertPHasValidCharacters: p from: sender.

But now, I can't see the assumption from within public API. I have to
browse implementors of assertPIsValid:, so I loose the immediate
documentation...

And one day, a brilliant programmer decide a ReadStream on characters
would also be a good parameter P, with a minor change in the core
method...
Arghh, I don't want to advance the stream yet and do all my static checks...

In order to maximize extendability, can't we use extensible assertions
like sending a message?
If we end up with
   [p isAGoodParameterPForMyMessage] assert.
then I don't buy it ;)

Maybe you have some better ideas about optional types as a specification...
Semi-automatic RoelTyper like helper tools?

Nicolas

> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: About TestCase >> assert:

Dale
In reply to this post by Mariano Martinez Peck
Nicolas, many very good points.

Just to add food for thought... double dispatching is a technique that has the benefit of avoiding isXXXX messages completely allowing for maximum flexibility and if the message isn't understood, immediate feedback that the programmer has done something wrong (which can be fixed by implementing the appropriate dispatch method) ... better than an assertion failures perhaps...

Of course, double dispatching is not without it's drawbacks. I prefer double dispatching to implementing isXXX messages, but then I'd like to eliminate Booleans, too:)

Dale
----- "Nicolas Cellier" <[hidden email]> wrote:

| 2009/10/16 Stéphane Ducasse <[hidden email]>:
| >
| >> I think Smalltalk quality is based on a completly different plane
| >
|
| First, my reference about quality is not Squeak, I rather mean st-80
| from ParcPlace :)
| At least it used to have
| - more generous class and method comments
| - less bugs and obscure code (certainly because less code too !)
| - a certain homogeneity (less programmers ?)
|
| So were is the Smalltalk quality ?
| - the ability to test code as soon as written
| - the ability to write small and simple code,
| - the ability to write readable code,
| - the ability to extend code
| Are these essential properties in the quality standards used in static
| typing ?
|
| > You mean not checkable documentation, absence of documentation,
| > lack of static typing to document (because what would be good is to
| > have a pluggable type system)
| >
|
| I agree, lack of type can be seen as a weakness for documenting APIs.
| As a workaround, we use funny parameter names (anArrayOfStrings).
| Or we add a method comment (hem... at least we should).
| I agree, all these comments will become false when code is changed,
| and the quality will decrease...
| As false as an outdated assertion... but silent... Maybe it's worse ?
| Browsing senders, or inspecting the signature of message sent to, or
| inserting a halt is sometimes our solutions...
| I agree, this is not ideal.
|
| So yes, assertions as a public declaration of API could be good for
| documenting.
| And a good description of assertion failure can also provide
| informative feedback to the user (more than a Debugger ?)
|
| What I do not like is defensive assertions as a potential barrier to
| extendability, because they correspond to a static view of code, a
| snapshot of current state.
| Smalltalk state does and will change. The image is living, and class
| structure not written on stone.
| Rapidly changing code is definitely not accepted as a quality
| standard...
|
| In a rapidly changing image, assertions could be a supplementary drag
| against change...
| Suppose I have a method accepting a String parameter P: p.
|     [p isString] assertWithDescription: 'method xxx only accept a
| String as parameter P'.
| Now maybe the method would have worked with a Text. I have been too
| restrictive:
|     [p isCharacters] assertWithDescription: 'method xxx only accept
| characters'.
| Now someone introduce WideString, and my code only work with
| ByteString.
|     [p isCharacters and: [p asString isByteString]]
| assertWithDescription: 'method xxx only accept byte characters'.
| Yes, but the method does not work with empty String, I add:
|     [p notEmpty] assertWithDescription: 'method xxx only accept non
| empty strings'.
| Nor does it with some control characters:
|     self assertPHasValidCharacters: p.
| Fortunately someone then correct the WideString case, now I can
| retract isByteString.
| Unfortunately, p will be stored in an inst. var. with many public
| interfaces...
| Each time, I have to change all the false assertions in all senders
| of
| the core method that are in the public API...
| And maybe some of these public APIs are driven by other public APIs
| (you meet this in Smalltalk, didn't you?)
| To avoid this I create a specific method
| assertPIsValid: p
|     | sender |
|     sender := thisContext sender homeContext selector.
|     [p isCharacters] assertWithDescription: 'method ' , sender , '
| only accept characters'.
|     [p asString isByteString] assertWithDescription: 'method ' ,
| sender , ' only accept byte characters'.
|     [p notEmpty] assertWithDescription: 'method ' , sender , ' only
| accept non empty strings'.
|     self assertPHasValidCharacters: p from: sender.
|
| But now, I can't see the assumption from within public API. I have to
| browse implementors of assertPIsValid:, so I loose the immediate
| documentation...
|
| And one day, a brilliant programmer decide a ReadStream on characters
| would also be a good parameter P, with a minor change in the core
| method...
| Arghh, I don't want to advance the stream yet and do all my static
| checks...
|
| In order to maximize extendability, can't we use extensible
| assertions
| like sending a message?
| If we end up with
|    [p isAGoodParameterPForMyMessage] assert.
| then I don't buy it ;)
|
| Maybe you have some better ideas about optional types as a
| specification...
| Semi-automatic RoelTyper like helper tools?
|
| Nicolas
|
| > _______________________________________________
| > Pharo-project mailing list
| > [hidden email]
| > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
| >
|
| _______________________________________________
| Pharo-project mailing list
| [hidden email]
| http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: About TestCase >> assert:

Nicolas Cellier
Hehe, yes, once I implemented a matlab like generalized access:

m(1) = 3.14; % single element
m(1:5) = [2 3 9 7 1]; % a contiguous subspace
m([1 2 5]) = -m([1 2 5]); % an arbitrary subspace
m(:) = m(end:-1:1); % a whole subspace (colon = column matrix)
m( m>2 ) = m( m> 2 ) - 2; % a mask of booleans
m( m<0 ) = 0; % variant: fill a subspace with an element
m( m>5 ) = []; % a remove operation

To keep it extensible and avoid static type checks, i ended up with
triple dispatching...
Not the code I'm the most proud of.
I must admit a static-type compiler can handle such situations better...
Maybe some declarative rules rather than procedural would also help...

Nicolas

2009/10/20 Dale Henrichs <[hidden email]>:

> Nicolas, many very good points.
>
> Just to add food for thought... double dispatching is a technique that has the benefit of avoiding isXXXX messages completely allowing for maximum flexibility and if the message isn't understood, immediate feedback that the programmer has done something wrong (which can be fixed by implementing the appropriate dispatch method) ... better than an assertion failures perhaps...
>
> Of course, double dispatching is not without it's drawbacks. I prefer double dispatching to implementing isXXX messages, but then I'd like to eliminate Booleans, too:)
>
> Dale
> ----- "Nicolas Cellier" <[hidden email]> wrote:
>
> | 2009/10/16 Stéphane Ducasse <[hidden email]>:
> | >
> | >> I think Smalltalk quality is based on a completly different plane
> | >
> |
> | First, my reference about quality is not Squeak, I rather mean st-80
> | from ParcPlace :)
> | At least it used to have
> | - more generous class and method comments
> | - less bugs and obscure code (certainly because less code too !)
> | - a certain homogeneity (less programmers ?)
> |
> | So were is the Smalltalk quality ?
> | - the ability to test code as soon as written
> | - the ability to write small and simple code,
> | - the ability to write readable code,
> | - the ability to extend code
> | Are these essential properties in the quality standards used in static
> | typing ?
> |
> | > You mean not checkable documentation, absence of documentation,
> | > lack of static typing to document (because what would be good is to
> | > have a pluggable type system)
> | >
> |
> | I agree, lack of type can be seen as a weakness for documenting APIs.
> | As a workaround, we use funny parameter names (anArrayOfStrings).
> | Or we add a method comment (hem... at least we should).
> | I agree, all these comments will become false when code is changed,
> | and the quality will decrease...
> | As false as an outdated assertion... but silent... Maybe it's worse ?
> | Browsing senders, or inspecting the signature of message sent to, or
> | inserting a halt is sometimes our solutions...
> | I agree, this is not ideal.
> |
> | So yes, assertions as a public declaration of API could be good for
> | documenting.
> | And a good description of assertion failure can also provide
> | informative feedback to the user (more than a Debugger ?)
> |
> | What I do not like is defensive assertions as a potential barrier to
> | extendability, because they correspond to a static view of code, a
> | snapshot of current state.
> | Smalltalk state does and will change. The image is living, and class
> | structure not written on stone.
> | Rapidly changing code is definitely not accepted as a quality
> | standard...
> |
> | In a rapidly changing image, assertions could be a supplementary drag
> | against change...
> | Suppose I have a method accepting a String parameter P: p.
> |     [p isString] assertWithDescription: 'method xxx only accept a
> | String as parameter P'.
> | Now maybe the method would have worked with a Text. I have been too
> | restrictive:
> |     [p isCharacters] assertWithDescription: 'method xxx only accept
> | characters'.
> | Now someone introduce WideString, and my code only work with
> | ByteString.
> |     [p isCharacters and: [p asString isByteString]]
> | assertWithDescription: 'method xxx only accept byte characters'.
> | Yes, but the method does not work with empty String, I add:
> |     [p notEmpty] assertWithDescription: 'method xxx only accept non
> | empty strings'.
> | Nor does it with some control characters:
> |     self assertPHasValidCharacters: p.
> | Fortunately someone then correct the WideString case, now I can
> | retract isByteString.
> | Unfortunately, p will be stored in an inst. var. with many public
> | interfaces...
> | Each time, I have to change all the false assertions in all senders
> | of
> | the core method that are in the public API...
> | And maybe some of these public APIs are driven by other public APIs
> | (you meet this in Smalltalk, didn't you?)
> | To avoid this I create a specific method
> | assertPIsValid: p
> |     | sender |
> |     sender := thisContext sender homeContext selector.
> |     [p isCharacters] assertWithDescription: 'method ' , sender , '
> | only accept characters'.
> |     [p asString isByteString] assertWithDescription: 'method ' ,
> | sender , ' only accept byte characters'.
> |     [p notEmpty] assertWithDescription: 'method ' , sender , ' only
> | accept non empty strings'.
> |     self assertPHasValidCharacters: p from: sender.
> |
> | But now, I can't see the assumption from within public API. I have to
> | browse implementors of assertPIsValid:, so I loose the immediate
> | documentation...
> |
> | And one day, a brilliant programmer decide a ReadStream on characters
> | would also be a good parameter P, with a minor change in the core
> | method...
> | Arghh, I don't want to advance the stream yet and do all my static
> | checks...
> |
> | In order to maximize extendability, can't we use extensible
> | assertions
> | like sending a message?
> | If we end up with
> |    [p isAGoodParameterPForMyMessage] assert.
> | then I don't buy it ;)
> |
> | Maybe you have some better ideas about optional types as a
> | specification...
> | Semi-automatic RoelTyper like helper tools?
> |
> | Nicolas
> |
> | > _______________________________________________
> | > Pharo-project mailing list
> | > [hidden email]
> | > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
> | >
> |
> | _______________________________________________
> | Pharo-project mailing list
> | [hidden email]
> | http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: About TestCase >> assert:

Stéphane Ducasse
In reply to this post by Nicolas Cellier
> First, my reference about quality is not Squeak, I rather mean st-80
> from ParcPlace :)

:)

> At least it used to have
> - more generous class and method comments
> - less bugs and obscure code (certainly because less code too !)
> - a certain homogeneity (less programmers ?)

Yes!

> So were is the Smalltalk quality ?
> - the ability to test code as soon as written
> - the ability to write small and simple code,
> - the ability to write readable code,
> - the ability to extend code
> Are these essential properties in the quality standards used in  
> static typing ?

But contracts and pre and cons are not linked with static typing.

>> You mean not checkable documentation, absence of documentation,
>> lack of static typing to document (because what would be good is to
>> have a pluggable type system)
>
> I agree, lack of type can be seen as a weakness for documenting APIs.
> As a workaround, we use funny parameter names (anArrayOfStrings).
> Or we add a method comment (hem... at least we should).
> I agree, all these comments will become false when code is changed,
> and the quality will decrease...

No this is not only that is that if you have precondition you localize  
the origin
of bugs.


> As false as an outdated assertion... but silent... Maybe it's worse ?
> Browsing senders, or inspecting the signature of message sent to, or
> inserting a halt is sometimes our solutions...
> I agree, this is not ideal.
>
> So yes, assertions as a public declaration of API could be good for  
> documenting.

I'm not sure that this is what I implied. For me pre and post are a  
nice way to
specify the responsibility of the caller and the callee.

> And a good description of assertion failure can also provide
> informative feedback to the user (more than a Debugger ?)
>
> What I do not like is defensive assertions as a potential barrier to
> extendability, because they correspond to a static view of code, a
> snapshot of current state.

I agree.
I would avoid to have
        self assert: [aParam isKindOf: Point]

> Smalltalk state does and will change. The image is living, and class
> structure not written on stone.
> Rapidly changing code is definitely not accepted as a quality  
> standard...
>
> In a rapidly changing image, assertions could be a supplementary drag
> against change...
> Suppose I have a method accepting a String parameter P: p.
>    [p isString] assertWithDescription: 'method xxx only accept a
> String as parameter P'.
> Now maybe the method would have worked with a Text. I have been too  
> restrictive:
>    [p isCharacters] assertWithDescription: 'method xxx only accept  
> characters'.
> Now someone introduce WideString, and my code only work with  
> ByteString.
>    [p isCharacters and: [p asString isByteString]]
> assertWithDescription: 'method xxx only accept byte characters'.
> Yes, but the method does not work with empty String, I add:
>    [p notEmpty] assertWithDescription: 'method xxx only accept non
> empty strings'.

I would prefer to have
        [p isStringable]
                string implements Stringable
                Text implements Stringable

I think that this is not because we have a dynamically typed language  
that we should forget
consistent/compatible types (expressed via an agreement on common  
protocol).

> Maybe you have some better ideas about optional types as a  
> specification...
> Semi-automatic RoelTyper like helper tools?

Do not confuse preconditions and type annotation. For me precondition  
is also  about
the object state before the method execution.

So what we should do is learn what could be good.

Stef

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
12