cuke-step-bm 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|