On Sat, 2007-02-03 at 07:05 +0900, Jeff wrote:
> I'm looking into a way to let business users write functional tests in
> rails, and I wanted to have my functional test file load an external
> file to supply the body of a method.  It occurs to me that Rake must
> have solved a similar problem, but I can't quite figure out how Jim
> did it.
> 
> What I want to write is something like this:
> 
> class MyTests < Test::Unit::TestCase
> 
>  # typical setup and teardown here
> 
>  # a test method to "wrap" an external ruby file
> 
>  def test_acceptance
>    load 'acceptance.rb'  # load file written by business user
>  end
> 
>  def foo
>  end
> 
>  def bar
>  end
> 
> end
> 
> I admit it didn't look right when I wrote it.  I had hoped that the
> code in acceptance.rb could be bare Ruby code.  in other words, it
> would look like and feel top-level Ruby, but could call foo and bar
> because it's really in the midst of the test_acceptance method.
> 
> So I conclude that load() starts a new scope.  I guess I could add my
> methods to Object and/or Module to get them to be seen by the external
> file, but I don't think that does any good either.
> 
> But Rake does something similar, right?  I think it defines the task()
> method, etc. and you can refer to them in "bare" ruby code in your
> rake file.
> 
> What glue is being used in Rake that I'm missing?
> 
> Thanks!
> Jeff

I think I get your point. This is what I'd do, though:

  module TestContainer
    class << self
      def tests
        @tests ||= {}
      end
      
      def define_test(name, &body)
        @tests[name] = body
      end
    end
  end

  module Kernel
    def test(name, &body)
      TestContainer.define_test(name, &body)
    end
  end

Then you can just go and do:

  # foo_test.rb
  test :foo do
    assert_equal 4, 2 * 2
  end

And then, in your test file:

  require 'foo_test'

  class MyTest < Test::Unit::TestCase
    TestContainer.tests.each do |name, body|
      define_method("test_#{name}", &body)
    end
  end



Cheers,
Daniel