使用示例

setup 用来设置每个测试的前置环境;

每个event相互独立, 实例变量不能相互干扰.

setup do
  @target_price = 100
end

setup do
  @target_weight = 1.5
end

event "cheaper" do
  111 > @target_price
end

event "heavier" do
  1.8 > @target_weight
end

event "test 1" do
  # sth...
  @v = 123
  true
end

event "test 2" do
  # sth...
  puts @v if @v
  true
end

event "test 3" do
  # sth...
  false
end

demo1 直接绑在顶层

@setup = []

def setup(&block)
  @setup << block
end

@events = []

def event(descp, &block)
  @events << {
      descption: descp,
      condition: block
  }
end

load "event.rb"

@events.each do |event|
  env = Object.new

  @setup.each do |setup|
    env.instance_eval &setup
    # setup.call
  end

  # if event[:condition].call
  if env.instance_eval &(event[:condition])
    printf "."
  else
    printf "e"
  end
end

puts ""

demo2 使用lambda限定影响范围

lambda {
  setups = []
  events = []

  Kernel.send :define_method, :setup do |&block|
    setups << block
  end

  Kernel.send :define_method, :event do |descp, &block|
    events << {
        descption: descp,
        condition: block
    }
  end

  Kernel.send :define_method, :each_setup do |&block|
    setups.each do |setup|
      block.call setup
    end
  end

  Kernel.send :define_method, :each_event do |&block|
    events.each do |event|
      block.call event
    end
  end

}.call

load "event.rb"

each_event do |event|
  env = Object.new
  each_setup do |setup|
    env.instance_eval &setup
  end

  if env.instance_eval &(event[:condition])
    printf "."
  else
    printf "e"
  end
end

puts ""

instance_eval 接收一个 block 后, 直接在对应的上下文执行. 如果需要传参, 可以使用 instance_exec .