1

所以,我试图解析一个 Cucumber 文件(*.feature),以确定每个场景有多少行。

文件示例:


    Scenario: Add two numbers 
       Given I have entered 50 into the calculator
       And I have entered 70 into the calculator
       When I press add
       Then the result should be 120 on the screen

    Scenario: Add many numbers
       Given I have entered 50 into the calculator
       And I have entered 20 into the calculator
       And I have entered 20 into the calculator
       And I have entered 30 into the calculator
       When I press add
       Then the result should be 120 on the screen

所以,我期待解析这个文件并得到如下结果:

场景:添加两个数字 ---> 它有 4 行!

场景:添加许多数字 ---> 它有 6 行!

最好的方法是什么?

4

4 回答 4

1

你为什么不从简单的开始?就像@FeRtoll 建议的那样,逐行进行可能是最简单的解决方案。像以下这样简单的东西可能就是您正在寻找的东西:

scenario  = nil
scenarios = Hash.new{ |h,k| h[k] = 0 }

File.open("file_or_argv[0]_or_whatever.features").each do |line|
  next if line.strip.empty?

  if line[/^Scenario/]
    scenario = line
  else
    scenarios[scenario] += 1
  end
end

p scenarios

输出 :

{"Scenario: Add two numbers \n"=>4, "Scenario: Add many numbers\n"=>6}
于 2013-04-06T21:51:13.587 回答
1

Enumerable#slice_before几乎是为此量身定做的。

File.open('your cuke scenario') do |f|
  f.slice_before(/^\s*Scenario:/) do |scenario|
    title = scenario.shift.chomp
    ct = scenario.map(&:strip).reject(&:empty?).size
    puts "#{title} --> has #{ct} lines"
  end
end
于 2013-04-06T21:59:43.737 回答
0

FeRtoll 提出了一个很好的方法:按部分累积。为我解析它的最简单方法是清除我可以忽略的部分(即评论),然后分成几个部分:

file = ARGV[0] or raise "Please supply a file name to parse"

def preprocess file
  data = File.read(file)
  data.gsub! /#.+$/, ''    # strip (ignore) comments
  data.gsub! /@.+$/, ''    # strip (ignore) tags
  data.gsub! /[ \t]+$/, '' # trim trailing whitespace
  data.gsub! /^[ \t]+/, '' # trim leading whitespace
  data.split /\n\n+/       # multiple blanks separate sections
end

sections = {
  :scenarios    => [],
  :background   => nil,
  :feature      => nil,
  :examples     => nil
}

parts = preprocess file

parts.each do |part|
  first_line, *lines = part.split /\n/

  if first_line.include? "Scenario:"
    sections[:scenarios] << {
      :name  => first_line.strip,
      :lines => lines
    }
  end

  if first_line.include? "Feature:"
    sections[:feature] = {
      :name  => first_line.strip,
      :lines => lines
    }
  end

  if first_line.include? "Background:"
    sections[:background] = {
      :name  => first_line.strip,
      :lines => lines
    }
  end
  if first_line.include? "Examples:"
    sections[:examples] = {
      :name  => first_line.strip,
      :lines => lines
    }
  end
end

if sections[:feature]
  puts "Feature has #{sections[:feature][:lines].size} lines."
end

if sections[:background]
  puts "Background has #{sections[:background][:lines].size} steps."
end

puts "There are #{sections[:scenarios].size} scenarios:"
sections[:scenarios].each do |scenario|
  puts "  #{scenario[:name]} has #{scenario[:lines].size} steps"
end

if sections[:examples]
  puts "Examples has #{sections[:examples][:lines].size} lines."
end

高温高压

于 2013-04-06T21:48:39.997 回答
0

这是我正在处理的当前代码(基于 Kyle Burton 方法):

def get_scenarios_info
    @scenarios_info = [:scenario_name => "", :quantity_of_steps => []]
    @all_files.each do |file|
        line_counter = 0
        File.open(file).each_line do |line|
            line.chomp!
            next if line.empty?
            line_counter = line_counter + 1
            if line.include? "Scenario:"
                @scenarios_info << {:scenario_name => line, :scenario_line => line_counter, :feature_file => file, :quantity_of_steps => []}
                next
            end
            @scenarios_info.last[:quantity_of_steps] << line
        end
    end
    #TODO: fix me here!
    @scenarios_info.each do |scenario|
        if scenario[:scenario_name] == ""
            @scenarios_info.delete(scenario)
        end
        scenario[:quantity_of_steps] = scenario[:quantity_of_steps].size
    end
    puts @scenarios_info
end
于 2013-04-08T00:35:09.620 回答