Chain Method in Class with Method in Module

Discussion in 'Ruby' started by Raymond O'Connor, Dec 10, 2009.

  1. I'd like to chain setup in a unit test, so that it calls a method in a
    module BEFORE running through the setup code. I'd like to do it without
    having to put super() in the test's setup method.

    module MyModule
    module InstanceMethods
    def setup
    puts 'module setup'
    end
    end

    def self.included(base)
    base.send :include, InstanceMethods
    end
    end

    class MyUnitTest < Test::Unit::TestCase
    include MyModule

    def setup
    puts 'class setup'
    end

    end

    If this were working when I run a test in MyUnitTest it should print out
    module setup
    class setup

    Unfortunately I can't get it to work. Even with alias_method, I run
    into problems it seems because the class setup is defined after the
    module is included. Anyone one have any ideas?

    Thanks!
    --
    Posted via http://www.ruby-forum.com/.
    Raymond O'Connor, Dec 10, 2009
    #1
    1. Advertising

  2. On Thu, Dec 10, 2009 at 01:33:58PM +0900, Raymond O'Connor wrote:
    > I'd like to chain setup in a unit test, so that it calls a method in a
    > module BEFORE running through the setup code. I'd like to do it without
    > having to put super() in the test's setup method.


    What's wrong with super()? We use it in all of our other objects.
    Tests are normal objects too. :)

    --
    Aaron Patterson
    http://tenderlovemaking.com/
    Aaron Patterson, Dec 10, 2009
    #2
    1. Advertising

  3. Aaron Patterson wrote:
    > On Thu, Dec 10, 2009 at 01:33:58PM +0900, Raymond O'Connor wrote:
    >> I'd like to chain setup in a unit test, so that it calls a method in a
    >> module BEFORE running through the setup code. I'd like to do it without
    >> having to put super() in the test's setup method.

    >
    > What's wrong with super()? We use it in all of our other objects.
    > Tests are normal objects too. :)


    Trying to keep things as encapsulated as possible. Just seems wrong
    that people including the module need to know to call super in setup
    before their own setup code.
    --
    Posted via http://www.ruby-forum.com/.
    Raymond O'Connor, Dec 10, 2009
    #3
  4. On 10.12.2009 07:55, Raymond O'Connor wrote:
    > Aaron Patterson wrote:
    >> On Thu, Dec 10, 2009 at 01:33:58PM +0900, Raymond O'Connor wrote:
    >>> I'd like to chain setup in a unit test, so that it calls a method in a
    >>> module BEFORE running through the setup code. I'd like to do it without
    >>> having to put super() in the test's setup method.

    >> What's wrong with super()? We use it in all of our other objects.
    >> Tests are normal objects too. :)

    >
    > Trying to keep things as encapsulated as possible. Just seems wrong
    > that people including the module need to know to call super in setup
    > before their own setup code.


    That's the normal way to do business with super classes - and included
    modules. If you look at MyUnitTest.ancestors you will see that the
    class is first in the chain and *then* the included module appears.
    That's why #setup of your class is always invoked before #setup in any
    included module.

    Another solution to what you want to do would be this: use the template
    method pattern.

    module InstanceMethods
    def setup
    puts 'module setup'
    setup_local
    end

    def setup_local
    raise "Sub class needs to implement this!"
    end
    end

    class MyUnitTest < Test::Unit::TestCase
    include InstanceMethods

    def setup_local
    puts 'class setup'
    end
    end

    Although you can still break the pattern by defining #setup in the class
    because Ruby does not have final methods (e.g. like Java).

    Raymond, why do you use two modules here? As far as I can see there is
    no use case for a second module. Also, you could make InstanceMethods a
    regular class which inherits Test::Unit::TestCase. Placing this in a
    module only pays off if you want to include the module in classes which
    need to have differing super classes.

    A completely alternative way would be to define a mini DSL where you
    have full control over what happens:

    # untested
    def test(&b)
    Class.new do
    def setup
    puts 'module setup'
    super
    end
    end.send:)include, Module.new(&b))
    end

    MyUnitTest = test do
    def setup
    puts 'class setup'
    end
    end

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Dec 10, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patrick

    Delay chain

    Patrick, Dec 21, 2004, in forum: VHDL
    Replies:
    1
    Views:
    1,463
    Mike Treseler
    Dec 21, 2004
  2. Davy
    Replies:
    10
    Views:
    2,972
    Javier Castillo
    Dec 19, 2005
  3. Jeremy
    Replies:
    0
    Views:
    392
    Jeremy
    Jun 23, 2004
  4. E11
    Replies:
    1
    Views:
    4,736
    Thomas Weidenfeller
    Oct 12, 2005
  5. Iñaki Baz Castillo
    Replies:
    3
    Views:
    149
    Iñaki Baz Castillo
    May 2, 2008
Loading...

Share This Page