Properly extending test::unit to add logging

Hi,

I'd like to open up test::unit to add default logging to setup and
teardown. In java I did this with a base test class that every other
test extended, but that was never very nice as you had to remember to
call super in subclasses. The other option was adding aspects and all
that complexity. So I thought I could do it nicer in ruby with the
following:

  alias_method :old_setup, :setup
  def setup
    logger.debug "**** Beginning setup for: #{name} ****"
    old_setup
  end

Is this the proper way to extend builtin methods, and still preserve
the old behavior? I'm thinking the timing that the above code gets
called is important. Right now I'm getting one test error when I
extend setup as above, as opposed to leaving it out, so I must be dong
something wrong.

Btw - this w/i a Rails app (the above code is w/i test_helper), but I
figured this is more ruby then rails specific.

thanks,
Rob

···

--
http://www.robsanheim.com


http://www.ajaxian.com

whenever you wrap methods like this __always__, __always__, __always__ do this

   alias_method "old_method", "method"

   def method *a, &b
     # ...
     old_method *a, &b
     # ...
   end

you need to collect any args and block and pass them through.

regards.

-a

···

On Thu, 8 Jun 2006, Rob Sanheim wrote:

Hi,

I'd like to open up test::unit to add default logging to setup and
teardown. In java I did this with a base test class that every other
test extended, but that was never very nice as you had to remember to
call super in subclasses. The other option was adding aspects and all
that complexity. So I thought I could do it nicer in ruby with the
following:

alias_method :old_setup, :setup
def setup
  logger.debug "**** Beginning setup for: #{name} ****"
  old_setup
end

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Thanks for the tip. Besides that, are there any other gotchas related
to redefining methods? For instance, I'm redefining my_foo inside
module x, but y and z call my_foo before module x ever needs to get
loaded. Does that mean that my_foo will be the old version for y and
z, then the new version for any callers after module x gets loaded?

- rob

···

On 6/7/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

whenever you wrap methods like this __always__, __always__, __always__ do this

   alias_method "old_method", "method"

   def method *a, &b
     # ...
     old_method *a, &b
     # ...
   end

you need to collect any args and block and pass them through.

regards.

--

>whenever you wrap methods like this __always__, __always__, __always__ do
>this
>
> alias_method "old_method", "method"
>
> def method *a, &b
> # ...
> old_method *a, &b
> # ...
> end
>
>you need to collect any args and block and pass them through.
>
>regards.
>

Thanks for the tip. Besides that, are there any other gotchas related
to redefining methods?

This one is at least as conspicuous as the above one, but just in case...

Try to come up with a more imaginative name than old_method for the old
definition, or you'll get SystemStackErrors when somebody also overrides it
using the same name...

If the method doesn't take a block (or you're running 1.9), you can also use
the following idiom:

old_meth = instance_method(:method)
define_method(:method) do |*a| # &b too on 1.9
  # ...
  old_meth.bind(self).call(*a) # ditto
  # ...
end

which is safer name-clash-wise, but note that this is slower than the
alias_method mechanism.

For instance, I'm redefining my_foo inside
module x, but y and z call my_foo before module x ever needs to get
loaded. Does that mean that my_foo will be the old version for y and
z, then the new version for any callers after module x gets loaded?

Yes (if the later calls would see the new definition at all under the standard
method resolution rules).

···

On Thu, Jun 08, 2006 at 08:15:21AM +0900, Rob Sanheim wrote:

On 6/7/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby