root/lang/ruby/rspec-fixture/trunk/lib/spec/fixture/base.rb @ 6539

Revision 6539, 3.3 kB (checked in by walf443, 5 years ago)

lang/ruby/rspec-fixture:

  • fix a bug that is 'not converting collectly :msg in description template'.
  • add spec-fixture-base spec.
Line 
1class Spec::Fixture::Base
2  attr_reader :fixtures, :desc_template, :example_shared_runner
3
4  def initialize binding, hash, &block
5    @binding = binding
6    input_names, expected_name = *hash.to_a.first
7    unless input_names.kind_of? Array
8      input_names = [ input_names ]
9    end
10    _define_fixture(input_names, expected_name)
11    instance_eval(&block)
12  end
13
14  def it desc=nil, &example
15    if desc
16      @desc_template = desc
17    end
18    @example_shared_runner = example
19  end
20
21  def set_fixtures data
22    @fixtures = data.map do |item|
23      fxt, msg = *item
24      input, expected = *fxt.to_a.first
25      @class.new input, expected, msg, @filter_of
26    end
27  end
28
29  def filters hash
30    @filter_of = hash
31  end
32
33  def desc_filters hash
34    @desc_filter_of = hash
35  end
36
37  def generate_msg fxt
38    if @desc_template
39      msg = @desc_template
40      [ fxt._members, :msg ].flatten.each do |item|
41        if item == :msg
42          result = fxt.msg.to_s
43        else
44          result = fxt.value_of[item]
45          if @desc_filter_of && @desc_filter_of[item]
46            if @desc_filter_of[item].kind_of? Proc
47              result = @desc_filter_of[item].call(result)
48            else
49              [ @desc_filter_of[item] ].flatten.each do |meth|
50                result = result.__send__ meth
51              end
52            end
53          else
54            result = result.inspect
55          end
56        end
57        msg = msg.gsub(/:#{item.to_s}/, result)
58      end
59
60      msg
61    else
62      if fxt.msg
63        fxt.msg
64      else
65        ""
66      end
67    end
68  end
69
70  def run
71    fixture = self
72    @binding.module_eval do
73      if fixture.fixtures
74        fixture.fixtures.each do |fxt|
75          it fixture.generate_msg(fxt) do
76            fixture.example_shared_runner.call(fxt._input, fxt._expected)
77          end
78        end
79      end
80    end
81  end
82
83  # generate temp class for fixture.
84  def _define_fixture input, expected
85    klass = Class.new
86    klass.class_eval do
87      attr_reader :filter_of, :value_of, :msg
88
89      define_method :initialize do |_input, _expected, msg, filter_of|
90        @value_of = {}
91        @filter_of = filter_of ? filter_of : {}
92        if input.size == 1
93          key = input.first
94          @value_of[key] = _input
95        else
96          input.zip(_input) do |key, value|
97            @value_of[key] = value
98          end
99        end
100        @value_of[expected] = _expected
101        @msg = msg
102      end
103
104      define_method :_members do
105        [ input, expected].flatten
106      end
107
108      define_method :_expected do
109        __send__ expected
110      end
111
112      define_method :_input do
113        if input.size == 1
114          __send__(input.first)
115        else
116          result_of = {}
117          input.each do |item|
118            result_of[item] = __send__ item
119          end
120
121          result_of
122        end
123      end
124
125      [ input, expected ].flatten.each do |item|
126        raise NameError if instance_methods.map{|i| i.to_s }.include? item.to_s
127
128        define_method item do
129          result = @value_of[item]
130          if @filter_of[item].kind_of? Proc
131            result = @filter_of[item].call(result)
132          else
133            if @filter_of[item]
134              [ @filter_of[item] ].flatten.each do |filter|
135                result = result.__send__ filter
136              end
137            end
138          end
139
140          result
141        end
142      end
143    end
144
145    @class = klass
146  end
147end
Note: See TracBrowser for help on using the browser.