[email protected] wrote:
> Em  14/10/2009  17:11,  Alexandre  Bergel <[email protected]> escreveu:
> 
>>> In Squeak 3.10 TestCase >> assert: aBooleanOrBlock
>>> Squeak 3.8, Dolphin and VAST  (I don't know others) have: TestCase
>>>>> assert: aBoolean
>>> So...is there a reason of doing that? Is this expected?
>>  I  do not  see any  particular reason.  But  having Object>>assert:
>> aBlock  is important,  since one  can simply  redefine assert:  in a
>> class to supress all assertions.
> 
> Which begs the question: then why the same method is re-implemented in 
> TestCase anyway?

...just thinking 'aloud'...

TestCase>>assert:, by convention, accepts a Boolean, and could be 
extended to also accept a block (and apparently has been so extended in 
Squeak).

Object>>assert: *should* accept a block, and it isn't really useful for 
it to accept a Boolean.

As Alexandre says, you can suppress assertions by redefining #assert:. 
One could also make Object>>assert: depend on some variable somewhere to 
determine whether to actually run the assertion blocks. Then you can 
turn assertions on and off system-wide, and not be running that 
assertion code in the blocks all the time. If you accepted a boolean, 
you'd be running the assertion expression whether assertions were turned 
on or not, which is undesirable.

It's not too nice if Object>>assert: and TestCase>>assert: take 
different kinds of arguments

TestCase>>assert: takes a Boolean. I suspect that's too widely used to 
change.

I don't know how widely used Object>>assert: is. Perhaps we could have a 
different selector for that which takes a block. Maybe a selector that 
implies more strongly that its argument should be a block. Our test 
framework (which I believe predates SUnit) uses #run:forResult:, with a 
block for the first argument and the expected result of evaluating the 
block as the second argument. I like this for a couple of reasons -- 
run: strongly implies that it should take a block argument, and giving 
the expected result separately allows failure messages of the form 
"Expected <a>; got <b>" which is handy anytime but *really* useful when 
failures are not easily reproducible.


Regards,

-Martin


P.S. -- the following is marginally related:

In performance-critical code that is executed *very* frequently, even 
making a message send and checking whether assertions are turned on or 
not can have too much impact. In those situations, I banish all 
assertions to a subclass, which has methods of this general form:

   someMethod
     | result |
     self assert: [assertions appropriate on entry to this method].
     result := super someMethod.
     self assert: [assertions appropriate on exit from this method].
     ^result.

Then to turn assertions on or off, I have code that can change the class 
of the instances, and switch whether new instances are of the 
no-assertions class or the with-assertions subclass.

This allows the application to run at full speed when assertions are 
turned off, a real advantage in some cases. This also separates the 
normal code from the assertion code, which has both advantages and 
disadvantages.



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

Reply via email to