cuke-step-bm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +1 -0
- data/README.rdoc +32 -0
- data/Rakefile +1 -0
- data/bin/cuke-step-bm +6 -0
- data/cuke-step-bm.gemspec +23 -0
- data/features/steps_consuming.bms +4 -0
- data/features/test.feature +0 -0
- data/lib/cuke-step-bm.rb +114 -0
- data/lib/cuke-step-bm/cli.rb +271 -0
- data/test.rb +6 -0
- metadata +58 -0
data/Gemfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
source "http://rubygems.org"
|
data/README.rdoc
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
== Cucumber steps time-consuming
|
2
|
+
|
3
|
+
figure out which steps are slow.
|
4
|
+
|
5
|
+
== Configuration
|
6
|
+
|
7
|
+
* config/cuke_step_bm.rb or ~/.cuke_step_bm
|
8
|
+
|
9
|
+
output_mode:
|
10
|
+
# :bm => BenchMark(only for display)
|
11
|
+
# :std => SimpleTimeDiff
|
12
|
+
# :std_with_log => SimpleTimeDiff log
|
13
|
+
# :off => Cucumber default do nothing
|
14
|
+
|
15
|
+
CukeStepBm.configure do |config|
|
16
|
+
config.root = "/tmp"
|
17
|
+
config.output_mode = :std_with_log
|
18
|
+
config.log_file = File.join(config.root, 'steps_consuming.bms')
|
19
|
+
config.delimiter = "-#{[20879].pack("U*")}-"
|
20
|
+
end
|
21
|
+
|
22
|
+
== Command
|
23
|
+
|
24
|
+
cuke-step-bm -h for help
|
25
|
+
|
26
|
+
== TodoList Working in process
|
27
|
+
|
28
|
+
* add spec test
|
29
|
+
* add pp
|
30
|
+
* add color
|
31
|
+
* refator for something
|
32
|
+
* ..
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/cuke-step-bm
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "cuke-step-bm"
|
6
|
+
s.version = "1.0.0"
|
7
|
+
s.authors = ["elvuel"]
|
8
|
+
s.email = ["elvuel@gmail.com"]
|
9
|
+
s.homepage = "https://github.com/elvuel"
|
10
|
+
s.summary = %q{cucumber steps benchmark}
|
11
|
+
s.description = %q{cucumber steps benchmark}
|
12
|
+
|
13
|
+
s.rubyforge_project = "cuke-step-bm"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
# s.add_development_dependency "rspec"
|
22
|
+
# s.add_runtime_dependency "rest-client"
|
23
|
+
end
|
File without changes
|
data/lib/cuke-step-bm.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "cuke-step-bm/cli"
|
3
|
+
|
4
|
+
module CukeStepBm
|
5
|
+
# cuke_step_bm bm-cuke-step cuke-step-bm.rb
|
6
|
+
VERSION = "0.0.1".freeze
|
7
|
+
|
8
|
+
# :bm => BenchMark(only for display)
|
9
|
+
# :std => SimpleTimeDiff
|
10
|
+
# :std_with_log => SimpleTimeDiff log
|
11
|
+
# :off => Cucumber default do nothing
|
12
|
+
|
13
|
+
BM_SUPPORTED_OUTPUT_MODES = [:bm, :std, :std_with_log, :off]
|
14
|
+
|
15
|
+
class << self
|
16
|
+
attr_accessor :root, :log_file, :output_mode, :delimiter
|
17
|
+
|
18
|
+
def configure
|
19
|
+
yield self
|
20
|
+
end
|
21
|
+
|
22
|
+
def suite!
|
23
|
+
use_defaults!
|
24
|
+
paths = [
|
25
|
+
File.expand_path("config/cuke_step_bm.rb", root),
|
26
|
+
File.expand_path(".cuke_step_bm", root)
|
27
|
+
]
|
28
|
+
paths.each { |path| load(path) if File.exist?(path) }
|
29
|
+
self.output_mode = :std unless BM_SUPPORTED_OUTPUT_MODES.include? output_mode
|
30
|
+
end
|
31
|
+
|
32
|
+
def use_defaults!
|
33
|
+
configure do |config|
|
34
|
+
config.root = File.expand_path('.', Dir.pwd)
|
35
|
+
config.output_mode = :std
|
36
|
+
config.log_file = File.join(config.root, 'features', 'steps_consuming.bms')
|
37
|
+
config.delimiter = "-#{[20879].pack("U*")}-"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_to_log(msg)
|
42
|
+
File.open(log_file, "a+") { |f| f.write msg }
|
43
|
+
rescue
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
#remove log file before cuke working with :std_with_log
|
48
|
+
def remove_log!
|
49
|
+
File.delete log_file if File.exist?(log_file) && (output_mode == :std_with_log)
|
50
|
+
rescue Exception => e
|
51
|
+
warn e.message
|
52
|
+
end
|
53
|
+
|
54
|
+
end # class << self
|
55
|
+
end # CucumberStepsBm
|
56
|
+
|
57
|
+
CukeStepBm.suite!
|
58
|
+
|
59
|
+
if defined?(Cucumber) && defined?(Cucumber::VERSION) && (Cucumber::VERSION >= "1.1.1") && (CukeStepBm.output_mode != :off)
|
60
|
+
CukeStepBm.remove_log!
|
61
|
+
|
62
|
+
module Cucumber
|
63
|
+
module Ast
|
64
|
+
class StepInvocation #:nodoc:
|
65
|
+
def invoke(step_mother, configuration)
|
66
|
+
exec_proc = Proc.new {
|
67
|
+
find_step_match!(step_mother, configuration)
|
68
|
+
unless @skip_invoke || configuration.dry_run? || @exception || @step_collection.exception
|
69
|
+
@skip_invoke = true
|
70
|
+
begin
|
71
|
+
@step_match.invoke(@multiline_arg)
|
72
|
+
step_mother.after_step
|
73
|
+
status!(:passed)
|
74
|
+
rescue Pending => e
|
75
|
+
failed(configuration, e, false)
|
76
|
+
status!(:pending)
|
77
|
+
rescue Undefined => e
|
78
|
+
failed(configuration, e, false)
|
79
|
+
status!(:undefined)
|
80
|
+
rescue Cucumber::Ast::Table::Different => e
|
81
|
+
@different_table = e.table
|
82
|
+
failed(configuration, e, false)
|
83
|
+
status!(:failed)
|
84
|
+
rescue Exception => e
|
85
|
+
failed(configuration, e, false)
|
86
|
+
status!(:failed)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
}
|
90
|
+
|
91
|
+
if (CukeStepBm.output_mode == :bm) && defined?(Benchmark)
|
92
|
+
Benchmark.bm do |reporter|
|
93
|
+
reporter.report("Time consuming:") { exec_proc.call }
|
94
|
+
end
|
95
|
+
else
|
96
|
+
time_begin = Time.now
|
97
|
+
exec_proc.call
|
98
|
+
time_end = Time.now
|
99
|
+
time_for_output = "Step consume %s seconds.\n" % ["#{time_end - time_begin}"]
|
100
|
+
time_consuming_message = ["#{time_end - time_begin}", @name, file_colon_line].join(CukeStepBm.delimiter)
|
101
|
+
time_consuming_message << "\n"
|
102
|
+
if CukeStepBm.output_mode == :std_with_log
|
103
|
+
puts time_for_output
|
104
|
+
CukeStepBm.write_to_log time_consuming_message
|
105
|
+
else
|
106
|
+
puts time_for_output
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end # invoke
|
110
|
+
|
111
|
+
end # StepInvocation
|
112
|
+
end # Ast
|
113
|
+
end # Cucumber
|
114
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
#require 'ostruct'
|
5
|
+
|
6
|
+
module CukeStepBm
|
7
|
+
class Cli
|
8
|
+
|
9
|
+
class Options
|
10
|
+
#SCOPES = [:step, :feature]
|
11
|
+
def parse!(args)
|
12
|
+
options = {}
|
13
|
+
opt_parser = OptionParser.new("", 30, ' ') do |opts|
|
14
|
+
opts.banner = "Usage: cuke-step-bm options"
|
15
|
+
|
16
|
+
opts.on("-f", "--feature FEATURE", String, "In specify feature") do |feature|
|
17
|
+
options[:feature] = feature
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-M", "--most", "Show the most time-consuming step") do
|
21
|
+
options[:act] = [ :most ]
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-t", "--total", "Show the total time-consuming") do
|
25
|
+
options[:act] = [ :total ]
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-w", "--within from,to", Array, "Show the steps time-consuming within the given range (use: -w 1,2)") do |from_to|
|
29
|
+
if from_to.size < 2
|
30
|
+
puts "wrong argument size"
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
options[:act] = [ :within, [from_to.first, from_to.last] ]
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-l", "--less VALUE", Float, "Show the steps time-consuming less than or equal the given") do |v|
|
37
|
+
options[:act] = [ :less, v ]
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-m", "--more VALUE", Float, "Show the steps time-consuming more than or equal the given") do |v|
|
41
|
+
options[:act] = [ :more, v ]
|
42
|
+
end
|
43
|
+
|
44
|
+
#opts.on("-s", "--scope value", "Show messages within scope (all/feature_filepath)") do |v|
|
45
|
+
# v = v.to_sym
|
46
|
+
# v = :step unless SCOPES.include? v
|
47
|
+
# options[:scope] = v
|
48
|
+
#end
|
49
|
+
|
50
|
+
opts.separator ""
|
51
|
+
opts.separator "Common options:"
|
52
|
+
|
53
|
+
opts.on_tail("-h", "--help", "Show this usage message") do
|
54
|
+
puts opts
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on_tail("-v", "--version", "Show version") do
|
59
|
+
puts "cuke-step-bm #{CukeStepBm::VERSION}"
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
end
|
63
|
+
opt_parser.parse! args
|
64
|
+
options
|
65
|
+
end
|
66
|
+
end # Options
|
67
|
+
|
68
|
+
|
69
|
+
def self.execute(args)
|
70
|
+
new(args).execute
|
71
|
+
end
|
72
|
+
|
73
|
+
#attr_reader :opt_parser
|
74
|
+
|
75
|
+
def initialize(args)
|
76
|
+
@config = CukeStepBm
|
77
|
+
@log_file = @config.log_file
|
78
|
+
bm_validate!
|
79
|
+
@options = Options.new.parse! args
|
80
|
+
@options = default_options.merge @options
|
81
|
+
@options[:act] = [ :most ] unless @options[:act]
|
82
|
+
#@scope = @options.delete :scope
|
83
|
+
end
|
84
|
+
|
85
|
+
def execute
|
86
|
+
parse_bms!
|
87
|
+
self.send *@options[:act]
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def most
|
92
|
+
the_most = @bms.sort_by { |item| item[:consume] }.last
|
93
|
+
if in_feature?
|
94
|
+
msg = "The most time-consuming in %s:\n\tLine: %s, Step: [ %s ], take %s seconds." % [
|
95
|
+
msg_color(the_most[:feature], "red"),
|
96
|
+
the_most[:line],
|
97
|
+
msg_color(the_most[:step], "red"),
|
98
|
+
msg_color(the_most[:consume])
|
99
|
+
]
|
100
|
+
info(msg)
|
101
|
+
else
|
102
|
+
msg = "The most time-consuming in all features:In %s, Line: %s, Step: [ %s ], take %s seconds.\n\n" % [
|
103
|
+
msg_color(the_most[:feature], "red"),
|
104
|
+
the_most[:line],
|
105
|
+
msg_color(the_most[:step], "red"),
|
106
|
+
msg_color(the_most[:consume])
|
107
|
+
]
|
108
|
+
info(msg)
|
109
|
+
feature_grp_hash = @bms.group_by { |item| item[:feature] }
|
110
|
+
feature_grp_hash.each do |feature, value|
|
111
|
+
the_most = value.sort_by { |item| item[:consume] }.last
|
112
|
+
msg = "In feature [ %s ]\n\tLine: %s, Step: [ %s ], take %s seconds.\n\n" % [
|
113
|
+
msg_color(the_most[:feature] || feature, "red"),
|
114
|
+
the_most[:line],
|
115
|
+
msg_color(the_most[:step], "red"),
|
116
|
+
msg_color(the_most[:consume])
|
117
|
+
]
|
118
|
+
info(msg)
|
119
|
+
end # grp_hash
|
120
|
+
|
121
|
+
end # in_feature?
|
122
|
+
end # most
|
123
|
+
|
124
|
+
def total
|
125
|
+
t_ary = @bms.collect { |item| item[:consume] }
|
126
|
+
sum = t_ary.inject(:+)
|
127
|
+
if in_feature?
|
128
|
+
feature = @bms.first[:feature]
|
129
|
+
info "Feature %s, %s steps total consume: %s seconds." % [msg_color(feature), msg_color(t_ary.size), msg_color(sum)]
|
130
|
+
else
|
131
|
+
msg = "Total consume: %s seconds.\n\n" % msg_color(sum)
|
132
|
+
info msg
|
133
|
+
feature_grp_hash = @bms.group_by { |item| item[:feature] }
|
134
|
+
feature_grp_hash.each do |feature, value|
|
135
|
+
t_ary = value.collect { |item| item[:consume] }
|
136
|
+
sum = t_ary.inject(:+)
|
137
|
+
msg = "\tFeature %s, %s steps total consume: %s seconds.\n\n" % [msg_color(feature), msg_color(t_ary.size), msg_color(sum)]
|
138
|
+
info msg
|
139
|
+
end
|
140
|
+
end # in_feature?
|
141
|
+
end # total
|
142
|
+
|
143
|
+
def within(args)
|
144
|
+
from, to = args.collect{ |arg| arg.to_f }
|
145
|
+
from, to = to, from if to < from
|
146
|
+
#grp_by = @bms.group_by { |item| in_feature? ? item[:step] : item[:feature] }
|
147
|
+
if in_feature?
|
148
|
+
grp_by_step = @bms.group_by { |item| item[:step] }
|
149
|
+
step_mean_hash= grp_by_step.inject({}) do |h, item|
|
150
|
+
key = item.shift
|
151
|
+
consumings = item.flatten.collect { |bm| bm[:consume] }
|
152
|
+
h[key] = consumings.inject(:+) / consumings.size
|
153
|
+
h
|
154
|
+
end
|
155
|
+
results = step_mean_hash.select { |k, v| (v >= from ) && (v <= to) }
|
156
|
+
feature = @bms.first[:feature]
|
157
|
+
unless results.empty?
|
158
|
+
info "In %s, Steps within %s .. %s" % [msg_color(feature), msg_color(from), msg_color(to)]
|
159
|
+
end
|
160
|
+
results.sort_by { |k, v| v }.each do |k, v|
|
161
|
+
info "\t Step %s, it average take %s seconds" % [msg_color(k), msg_color(v, "red")]
|
162
|
+
end
|
163
|
+
else
|
164
|
+
grp_by_feature = @bms.group_by { |item| item[:feature] }
|
165
|
+
grp_by_feature.each do |feature, all_steps|
|
166
|
+
grp_by_step = all_steps.group_by { |item| item[:step] }
|
167
|
+
step_mean_hash= grp_by_step.inject({}) do |h, item|
|
168
|
+
key = item.shift
|
169
|
+
consumings = item.flatten.collect { |bm| bm[:consume] }
|
170
|
+
h[key] = consumings.inject(:+) / consumings.size
|
171
|
+
h
|
172
|
+
end
|
173
|
+
results = step_mean_hash.select { |k, v| (v >= from ) && (v <= to) }
|
174
|
+
unless results.empty?
|
175
|
+
info "In %s, Steps within %s .. %s" % [msg_color(feature), msg_color(from), msg_color(to)]
|
176
|
+
end
|
177
|
+
results.sort_by { |k, v| v }.each do |k, v|
|
178
|
+
info "\t Step %s, it average take %s seconds" % [msg_color(k), msg_color(v, "red")]
|
179
|
+
end
|
180
|
+
end # grp_by_feature
|
181
|
+
end # in_feature?
|
182
|
+
end # within
|
183
|
+
|
184
|
+
def less_or_more(value, lom = "less")
|
185
|
+
value = value.to_f
|
186
|
+
if in_feature?
|
187
|
+
grp_by_step = @bms.group_by { |item| item[:step] }
|
188
|
+
step_mean_hash= grp_by_step.inject({}) do |h, item|
|
189
|
+
key = item.shift
|
190
|
+
consumings = item.flatten.collect { |bm| bm[:consume] }
|
191
|
+
h[key] = consumings.inject(:+) / consumings.size
|
192
|
+
h
|
193
|
+
end
|
194
|
+
results = step_mean_hash.select { |k, v| v.send((lom=="less") ? :<= : :>=, value) }
|
195
|
+
feature = @bms.first[:feature]
|
196
|
+
unless results.empty?
|
197
|
+
info "In %s, Steps %s than %s" % [msg_color(feature), msg_color(lom), msg_color(value)]
|
198
|
+
end
|
199
|
+
results.sort_by { |k, v| v }.each do |k, v|
|
200
|
+
info "\t Step %s, it average take %s seconds" % [msg_color(k), msg_color(v, "red")]
|
201
|
+
end
|
202
|
+
else
|
203
|
+
grp_by_feature = @bms.group_by { |item| item[:feature] }
|
204
|
+
grp_by_feature.each do |feature, all_steps|
|
205
|
+
grp_by_step = all_steps.group_by { |item| item[:step] }
|
206
|
+
step_mean_hash= grp_by_step.inject({}) do |h, item|
|
207
|
+
key = item.shift
|
208
|
+
consumings = item.flatten.collect { |bm| bm[:consume] }
|
209
|
+
h[key] = consumings.inject(:+) / consumings.size
|
210
|
+
h
|
211
|
+
end
|
212
|
+
results = step_mean_hash.select { |k, v| v.send((lom=="less") ? :<= : :>=, value) }
|
213
|
+
unless results.empty?
|
214
|
+
info "In %s, Steps %s than %s" % [msg_color(feature), msg_color(lom), msg_color(value)]
|
215
|
+
end
|
216
|
+
results.sort_by { |k, v| v }.each do |k, v|
|
217
|
+
info "\t Step %s, it average take %s seconds" % [msg_color(k), msg_color(v, "red")]
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end # in_feature?
|
221
|
+
end # less_or_more
|
222
|
+
|
223
|
+
def less(value)
|
224
|
+
less_or_more(value, "less")
|
225
|
+
end
|
226
|
+
|
227
|
+
def more(value)
|
228
|
+
less_or_more(value, "more")
|
229
|
+
end
|
230
|
+
|
231
|
+
def default_options
|
232
|
+
{ scope: :step, feature: :all }
|
233
|
+
end
|
234
|
+
|
235
|
+
def bm_validate!
|
236
|
+
abort "please make sure that record log file exist!" unless File.exist? @log_file
|
237
|
+
@bms ||= File.read(@log_file)
|
238
|
+
@bms.strip!
|
239
|
+
abort "record log file is empty!" if @bms.empty?
|
240
|
+
end
|
241
|
+
|
242
|
+
def parse_bms!
|
243
|
+
bms = @bms.split("\n")
|
244
|
+
bms.delete ""
|
245
|
+
bms.compact!
|
246
|
+
@bms = bms.inject([]) do |ary, item|
|
247
|
+
tmp_ary = item.split(@config.delimiter)
|
248
|
+
consume_time, step_name, file_colon_line = tmp_ary
|
249
|
+
feature, line = file_colon_line.split(":")
|
250
|
+
tmp_ary = { feature: feature, step: step_name, line: line, consume: consume_time.to_f }
|
251
|
+
ary << tmp_ary if @options[:feature].is_a?(Symbol) or (@options[:feature] == feature)
|
252
|
+
ary
|
253
|
+
end
|
254
|
+
abort msg_color("empty", "r") if @bms.empty?
|
255
|
+
end
|
256
|
+
|
257
|
+
def in_feature?
|
258
|
+
!@options[:feature].is_a?(Symbol)
|
259
|
+
end
|
260
|
+
|
261
|
+
def msg_color(msg, color="green")
|
262
|
+
color = (color == "green") ? 32 : 31
|
263
|
+
"\033[4;1;#{color};40m#{msg}\033[0m"
|
264
|
+
end
|
265
|
+
|
266
|
+
def info(msg)
|
267
|
+
puts msg
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
end
|
data/test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cuke-step-bm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- elvuel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-18 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: cucumber steps benchmark
|
15
|
+
email:
|
16
|
+
- elvuel@gmail.com
|
17
|
+
executables:
|
18
|
+
- cuke-step-bm
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- README.rdoc
|
25
|
+
- Rakefile
|
26
|
+
- bin/cuke-step-bm
|
27
|
+
- cuke-step-bm.gemspec
|
28
|
+
- features/steps_consuming.bms
|
29
|
+
- features/test.feature
|
30
|
+
- lib/cuke-step-bm.rb
|
31
|
+
- lib/cuke-step-bm/cli.rb
|
32
|
+
- test.rb
|
33
|
+
homepage: https://github.com/elvuel
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project: cuke-step-bm
|
53
|
+
rubygems_version: 1.8.10
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: cucumber steps benchmark
|
57
|
+
test_files: []
|
58
|
+
has_rdoc:
|