作为一个有趣的项目(如果有人感兴趣,可能是一个宝石),我试图实现一个基本的正则表达式匹配器(类似于Cucumber的工作方式),其语法看起来类似于shared_examples
。但我很难理解RSpec的基础以及如何解决这个问题。
这就是我的想象:
RSpec.describe do
define_example(/adds (\d+) plus (\d+) and gets (\d+)/) do |a, b, c|
it { expect(a + b).to eq(c) }
end
it_behaves_like_it 'adds 1 plus 1 and gets 2'
end
这样的实现:
class RegexExample
attr_accessor :spec_map
def initialize
@spec_map = []
end
def define_example(regex, &block)
spec_map << [regex, block]
end
def it_behaves_like_it(text)
spec_map_match = find_spec_map_match(text)
# Perhaps this should dynamically add a `it` test
# to the location calling it_behavies_like_it
it spec_map_match[2] do
spec_map_match[1].call(*spec_map_match[3])
end
end
private
def find_spec_map_match(text)
spec_map.each do |regex, block|
next unless (match = text.match(regex))
return [regex, block, text, typecast_captures(match.captures)]
end
end
def typecast_captures(matches)
matches.map do |m|
case m
when /\A\d+\Z/
m.to_i
else
m
end
end
end