lib/qed/script.rb in qed-1.1.0 vs lib/qed/script.rb in qed-1.2

- old
+ new

@@ -1,6 +1,7 @@ module QED + require 'yaml' require 'facets/dir/ascend' require 'ae' require 'qed/reporter/dotprogress' @@ -30,16 +31,21 @@ def initialize(file, output=nil) @file = file @output = output || Reporter::Verbatim.new #(self) source = File.read(file) - index = source.rindex('---') + index = source.rindex('---') || source.size @source = source[0...index] - @helper = source[index+3...-1].strip + @helper = source[index+3...-1].to_s.strip end + # File basename less extension. + def name + @name ||= File.basename(file).chomp(File.extname(file)) + end + #def convert # @source.gsub(/^\w/, '# \1') #end # Run the script. @@ -51,34 +57,86 @@ case step when /^[=#]/ output.report_header(step) when /^\S/ output.report_comment(step) + context.When.each do |(regex, proc)| + if md = regex.match(step) + proc.call(*md[1..-1]) + end + end else - run_step(step) + #if context.table + # run_table(step) + #else + run_step(step) + #end end end end # - def run_step(step, &blk) - context.before.call if context.before + def run_step(step=nil, &blk) + context.Before.call if context.Before begin if blk blk.call #eval(step, context._binding) else eval(step, context._binding, @file) # TODO: would be nice to know file and lineno here end - output.report_pass(step) + output.report_pass(step) if step rescue Assertion => error output.report_fail(step, error) rescue Exception => error output.report_error(step, error) ensure + context.After.call if context.After + end + end + +=begin + # + def run_table(step) + file = context.table + Dir.ascend(Dir.pwd) do |path| + f1 = File.join(path, file) + f2 = File.join(path, 'fixtures', file) + fr = File.file?(f1) ? f1 : File.exist?(f2) ? f2 : nil + (file = fr; break) if fr + end + output.report_pass(step) #step) + + tbl = YAML.load(File.new(file)) + key = tbl.shift + tbl.each do |set| + assign = key.zip(set).map{ |k, v| "#{k}=#{v.inspect};" }.join + run_table_step(assign + step, set) + #run_step(set.inspect.tabto(4)){ blk.call(set) } + #@_script.run_step(set.to_yaml.tabto(2)){ blk.call(set) } + #@_script.output.report_table(set) + end + #output.report_pass(step) #step) + context.table = nil + end + + # + #def run_table_step(step, set) + def run_table_step(set, &blk) + context.before.call if context.before + begin + #eval(step, context._binding, @file) # TODO: would be nice to know file and lineno here + blk.call(*set) + output.report_pass(' ' + set.inspect) #step) + rescue Assertion => error + output.report_fail(set.inspect, error) + rescue Exception => error + output.report_error(set.inspect, error) + ensure context.after.call if context.after end end +=end # Cut-up script into steps. def steps @steps ||= ( code = false @@ -86,18 +144,18 @@ steps = [] @source.each_line do |line| if /^\s*$/.match line str << line elsif /^[=]/.match line - steps << str.chomp("\n") - steps << line.chomp("\n") + steps << str #.chomp("\n") + steps << line #.chomp("\n") str = '' #str << line code = false elsif /^\S/.match line if code - steps << str.chomp("\n") + steps << str #.chomp("\n") str = '' str << line code = false else str << line @@ -112,10 +170,11 @@ code = true end end end steps << str + #steps.map{ |s| s.chomp("\n") } steps ) end # The run context. @@ -126,59 +185,107 @@ end # class Context < Module + TABLE = /^TABLE\[(.*?)\]/i + def initialize(script) @_script = script + @_when = [] + @_tables = [] end def _binding @_binding ||= binding end - # Set before step. - def before(&f) - @_before = f if f + # Before each step. + def Before(&procedure) + @_before = procedure if procedure @_before end - # Set after step. - def after(&f) - @_after = f if f + # After each step. + def After(&procedure) + @_after = procedure if procedure @_after end - # Table-based steps. - def table(file=nil, &blk) - require 'yaml' - - file ||= File.basename(@_script.file).chomp(File.extname(@_script.file)) + '.yaml' - - Dir.ascend(Dir.pwd) do |path| - f1 = File.join(path, file) - f2 = File.join(path, 'fixtures', file) - fr = File.file?(f1) ? f1 : File.exist?(f2) ? f2 : nil - (file = fr; break) if fr + # + def When(pattern=nil, &procedure) + return @_when unless procedure + raise ArgumentError unless pattern + unless Regexp === pattern + pattern = __when_string_to_regexp(pattern) end + @_when << [pattern, procedure] + end + # Table-based steps. + def Table(file=nil, &blk) + file = file || @_tables.last tbl = YAML.load(File.new(file)) tbl.each do |set| - @_script.run_step(set.to_yaml.tabto(2)){ blk.call(set) } - #@_script.output.report_table(set) + blk.call(*set) end + @_tables << file end - def fixture(fname, content=nil) - raise if File.directory?(fname) + # Read/Write a fixture. + def Data(file, &content) + raise if File.directory?(file) if content FileUtils.mkdir_p(File.dirname(fname)) - File.open(fname, 'w'){ |f| f << content } + case File.extname(file) + when '.yml', '.yaml' + File.open(file, 'w'){ |f| f << content.call.to_yaml } + else + File.open(file, 'w'){ |f| f << content.call } + end else - raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname) - File.read(fname) + #raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname) + case File.extname(file) + when '.yml', '.yaml' + YAML.load(File.new(file)) + else + File.read(file) + end end end + + private + + def __when_string_to_regexp(str) + str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x| + x =~ /\A\(\((.*)\)\)\z/ ? $1 : Regexp.escape(x) + }.join + str = str.gsub(/(\\\ )+/, '\s+') + Regexp.new(str, Regexp::IGNORECASE) + + #rexps = [] + #str = str.gsub(/\(\((.*?)\)\)/) do |m| + # rexps << '(' + $1 + ')' + # "\0" + #end + #str = Regexp.escape(str) + #rexps.each do |r| + # str = str.sub("\0", r) + #end + #str = str.gsub(/(\\\ )+/, '\s+') + #Regexp.new(str, Regexp::IGNORECASE) + end + + # + # check only local and maybe start paths + #def __locate_file(file) + # Dir.ascend(Dir.pwd) do |path| + # f1 = File.join(path, file) + # f2 = File.join(path, 'fixtures', file) + # fr = File.file?(f1) ? f1 : File.exist?(f2) ? f2 : nil + # (file = fr; break) if fr + # end + #end end end