parallel_cucumber 0.2.19 → 0.2.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/parallel_cucumber/cli.rb +0 -12
- data/lib/parallel_cucumber/dsl.rb +8 -0
- data/lib/parallel_cucumber/helper/command.rb +50 -37
- data/lib/parallel_cucumber/helper/cucumber/cucumber.rb +7 -0
- data/lib/parallel_cucumber/helper/cucumber/json_status_formatter.rb +1 -0
- data/lib/parallel_cucumber/helper/processes.rb +2 -2
- data/lib/parallel_cucumber/hooks.rb +29 -5
- data/lib/parallel_cucumber/main.rb +6 -2
- data/lib/parallel_cucumber/version.rb +1 -1
- data/lib/parallel_cucumber/worker.rb +7 -25
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c5786a5361ff67156526199fce9a686256fa49e33dc6c5af590c5f2ea17adce
|
4
|
+
data.tar.gz: 49d1792f94978bbfe9ea954e13dc9e0ebfe0742dad6aef966395e2885a462bdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc9332b43d59d80cedd19f8c2fd63cb231624e318a81a40fc378bd212e1dffb90aeb0ba7c359f6dae8cccec524d5f5828eb42d7f8e976a404ea5f7dba92ed283
|
7
|
+
data.tar.gz: 8f57b2ba36db0f161cfdf7db981411b365d8fc5d03b4369b388898c0e21b5e064331f4f91d154340a62075d16de4571e27ce406ee2eb84523a7156661dc45f77
|
@@ -8,7 +8,6 @@ module ParallelCucumber
|
|
8
8
|
batch_size: 1,
|
9
9
|
batch_timeout: 600,
|
10
10
|
setup_timeout: 30,
|
11
|
-
precheck_timeout: 30,
|
12
11
|
batch_error_timeout: 30,
|
13
12
|
cucumber_options: '',
|
14
13
|
debug: false,
|
@@ -90,10 +89,6 @@ module ParallelCucumber
|
|
90
89
|
options[:test_command] = test_command
|
91
90
|
end
|
92
91
|
|
93
|
-
opts.on('--pre-batch-check COMMAND', 'Command causing worker to quit on exit failure') do |pre_check|
|
94
|
-
options[:pre_check] = pre_check
|
95
|
-
end
|
96
|
-
|
97
92
|
opts.on('--log-dir DIR', 'Directory for worker logfiles') do |log_dir|
|
98
93
|
options[:log_dir] = log_dir
|
99
94
|
end
|
@@ -173,13 +168,6 @@ module ParallelCucumber
|
|
173
168
|
options[:batch_timeout] = batch_timeout
|
174
169
|
end
|
175
170
|
|
176
|
-
help_message = <<-TEXT.gsub(/\s+/, ' ').strip
|
177
|
-
Timeout for each test precheck. Default is #{DEFAULTS[:batch_timeout]}
|
178
|
-
TEXT
|
179
|
-
opts.on('--precheck-timeout SECONDS', Float, help_message) do |timeout|
|
180
|
-
options[:precheck_timeout] = timeout
|
181
|
-
end
|
182
|
-
|
183
171
|
help_message = <<-TEXT.gsub(/\s+/, ' ').strip
|
184
172
|
Timeout for each batch_error script. Default is #{DEFAULTS[:batch_error_timeout]}
|
185
173
|
TEXT
|
@@ -23,6 +23,10 @@ module ParallelCucumber
|
|
23
23
|
Hooks.register_after_batch(proc)
|
24
24
|
end
|
25
25
|
|
26
|
+
def worker_health_check(&proc)
|
27
|
+
Hooks.register_worker_health_check(proc)
|
28
|
+
end
|
29
|
+
|
26
30
|
def before_workers(&proc)
|
27
31
|
Hooks.register_before_workers(proc)
|
28
32
|
end
|
@@ -34,6 +38,10 @@ module ParallelCucumber
|
|
34
38
|
def on_batch_error(&proc)
|
35
39
|
Hooks.register_on_batch_error(proc)
|
36
40
|
end
|
41
|
+
|
42
|
+
def on_dry_run_error(&proc)
|
43
|
+
Hooks.register_on_dry_run_error(proc)
|
44
|
+
end
|
37
45
|
end
|
38
46
|
end
|
39
47
|
end
|
@@ -15,8 +15,13 @@ module ParallelCucumber
|
|
15
15
|
end
|
16
16
|
|
17
17
|
ONE_SECOND = 1
|
18
|
+
STACKTRACE_COLLECTION_TIMEOUT = 10
|
18
19
|
|
19
|
-
|
20
|
+
# rubocop:disable Metrics/ParameterLists, Metrics/LineLength
|
21
|
+
def exec_command(env, desc, script, logger, log_decoration = {},
|
22
|
+
timeout: 30, capture: false, return_script_error: false,
|
23
|
+
return_on_timeout: false, collect_stacktrace: false
|
24
|
+
)
|
20
25
|
block_name = ''
|
21
26
|
if log_decoration['worker_block']
|
22
27
|
if log_decoration['start'] || log_decoration['end']
|
@@ -28,42 +33,48 @@ module ParallelCucumber
|
|
28
33
|
full_script = "#{script} 2>&1"
|
29
34
|
env_string = env.map { |k, v| "#{k}=#{v}" }.sort.join(' ')
|
30
35
|
logger << "== Running command `#{full_script}` at #{Time.now}\n== with environment variables: #{env_string}\n"
|
31
|
-
|
36
|
+
wait_thread = nil
|
32
37
|
pout = nil
|
33
38
|
capture &&= [''] # Pass by reference
|
34
39
|
exception = nil
|
40
|
+
command_pid = nil
|
35
41
|
|
36
42
|
begin
|
37
43
|
completed = begin
|
38
|
-
pin, pout,
|
39
|
-
|
44
|
+
pin, pout, wait_thread = Open3.popen2e(env, full_script)
|
45
|
+
command_pid = wait_thread[:pid].to_s
|
46
|
+
logger << "Command has pid #{command_pid}\n"
|
40
47
|
pin.close
|
41
48
|
out_reader = Thread.new do
|
42
|
-
output_reader(pout,
|
49
|
+
output_reader(pout, wait_thread, logger, capture)
|
43
50
|
end
|
44
51
|
|
45
52
|
unless out_reader.join(timeout)
|
46
53
|
raise TimedOutError
|
47
54
|
end
|
48
55
|
|
49
|
-
graceful_process_shutdown(out_reader,
|
56
|
+
graceful_process_shutdown(out_reader, wait_thread, pout, logger)
|
50
57
|
|
51
|
-
|
52
|
-
"Command completed #{
|
58
|
+
wait_thread.value # reap already-terminated child.
|
59
|
+
"Command completed #{wait_thread.value} at #{Time.now}"
|
53
60
|
end
|
54
61
|
|
55
62
|
logger << "#{completed}\n"
|
56
63
|
|
57
|
-
raise "Script returned #{
|
64
|
+
raise "Script returned #{wait_thread.value.exitstatus}" unless wait_thread.value.success? || return_script_error
|
58
65
|
|
59
66
|
capture_or_empty = capture ? capture.first : '' # Even '' is truthy
|
60
|
-
return
|
67
|
+
return wait_thread.value.success? ? capture_or_empty : nil
|
61
68
|
rescue TimedOutError => e
|
62
|
-
|
69
|
+
process_tree = Helper::Processes.ps_tree
|
70
|
+
send_usr1_to_process_with_tree(command_pid, full_script, logger, process_tree) if collect_stacktrace
|
71
|
+
force_kill_process_with_tree(out_reader, wait_thread, pout, full_script, logger, timeout, process_tree, command_pid)
|
72
|
+
|
73
|
+
return capture.first if return_on_timeout
|
63
74
|
|
64
75
|
exception = e
|
65
76
|
rescue => e
|
66
|
-
logger.debug("Exception #{
|
77
|
+
logger.debug("Exception #{wait_thread ? wait_thread[:pid] : "wait_thread=#{wait_thread}=nil"}")
|
67
78
|
trace = e.backtrace.join("\n\t").sub("\n\t", ": #{$ERROR_INFO}#{e.class ? " (#{e.class})" : ''}\n\t")
|
68
79
|
logger.error("Threw for #{full_script}, caused #{trace}")
|
69
80
|
|
@@ -75,6 +86,7 @@ module ParallelCucumber
|
|
75
86
|
|
76
87
|
raise exception
|
77
88
|
end
|
89
|
+
# rubocop:enable Metrics/ParameterLists, Metrics/LineLength
|
78
90
|
|
79
91
|
def log_until_incomplete_line(logger, out_string)
|
80
92
|
loop do
|
@@ -87,13 +99,13 @@ module ParallelCucumber
|
|
87
99
|
|
88
100
|
private
|
89
101
|
|
90
|
-
def output_reader(pout,
|
102
|
+
def output_reader(pout, wait_thread, logger, capture)
|
91
103
|
out_string = ''
|
92
104
|
|
93
105
|
loop do
|
94
106
|
io_select = IO.select([pout], [], [], ONE_SECOND)
|
95
|
-
unless io_select ||
|
96
|
-
logger << "\n== Terminating because io_select=#{io_select} when
|
107
|
+
unless io_select || wait_thread.alive?
|
108
|
+
logger << "\n== Terminating because io_select=#{io_select} when wait_thread.alive?=#{wait_thread.alive?}\n"
|
97
109
|
break
|
98
110
|
end
|
99
111
|
next unless io_select
|
@@ -103,44 +115,45 @@ module ParallelCucumber
|
|
103
115
|
out_string = log_until_incomplete_line(logger, out_string + partial)
|
104
116
|
end
|
105
117
|
rescue EOFError
|
106
|
-
logger << "\n== EOF is normal exit, #{
|
118
|
+
logger << "\n== EOF is normal exit, #{wait_thread.inspect}\n"
|
107
119
|
rescue => e
|
108
120
|
logger << "\n== Exception in out_reader due to #{e.inspect} #{e.backtrace}\n"
|
109
121
|
ensure
|
110
122
|
logger << out_string
|
111
123
|
logger << ["\n== Left out_reader at #{Time.now}; ",
|
112
|
-
"pipe=#{
|
124
|
+
"pipe=#{wait_thread.status}+#{wait_thread.status ? '≤no value≥' : wait_thread.value}\n"].join
|
113
125
|
end
|
114
126
|
|
115
|
-
def graceful_process_shutdown(out_reader,
|
116
|
-
out_reader.value # Should terminate with
|
127
|
+
def graceful_process_shutdown(out_reader, wait_thread, pout, logger)
|
128
|
+
out_reader.value # Should terminate with wait_thread
|
117
129
|
pout.close
|
118
|
-
if
|
119
|
-
logger << "== Thread #{
|
130
|
+
if wait_thread.status
|
131
|
+
logger << "== Thread #{wait_thread.inspect} is not dead"
|
120
132
|
|
121
|
-
if
|
122
|
-
logger << "== Thread #{
|
133
|
+
if wait_thread.join(3)
|
134
|
+
logger << "== Thread #{wait_thread.inspect} joined late"
|
123
135
|
else
|
124
|
-
|
125
|
-
logger << "== Thread #{
|
136
|
+
wait_thread.terminate # Just in case
|
137
|
+
logger << "== Thread #{wait_thread.inspect} terminated"
|
126
138
|
end # Make an effort to reap
|
127
139
|
end
|
128
140
|
|
129
|
-
|
130
|
-
"Command completed #{
|
141
|
+
wait_thread.value # reap already-terminated child.
|
142
|
+
"Command completed #{wait_thread.value} at #{Time.now}"
|
131
143
|
end
|
132
144
|
|
133
|
-
def
|
145
|
+
def send_usr1_to_process_with_tree(command_pid, full_script, logger, tree)
|
146
|
+
return if Helper::Processes.ms_windows?
|
147
|
+
|
148
|
+
logger << "Timeout, so trying SIGUSR1 to trigger watchdog stacktrace #{command_pid}=#{full_script}"
|
149
|
+
Helper::Processes.kill_tree('SIGUSR1', command_pid, logger, tree)
|
150
|
+
sleep(STACKTRACE_COLLECTION_TIMEOUT) # Wait enough time for child processes to act on SIGUSR1
|
151
|
+
end
|
152
|
+
|
153
|
+
def force_kill_process_with_tree(out_reader, wait_thread, pout, full_script, logger, timeout, tree, pid) # rubocop:disable Metrics/ParameterLists, Metrics/LineLength
|
134
154
|
out_reader.exit
|
135
|
-
tree = Helper::Processes.ps_tree
|
136
|
-
pid = pstat[:pid].to_s
|
137
|
-
unless Helper::Processes.ms_windows?
|
138
|
-
logger << "Timeout, so trying SIGUSR1 to trigger watchdog stacktrace #{pstat[:pid]}=#{full_script}"
|
139
|
-
Helper::Processes.kill_tree('SIGUSR1', pid, logger, tree)
|
140
|
-
sleep 2
|
141
|
-
end
|
142
155
|
|
143
|
-
logger << "Timeout, so trying SIGINT at #{
|
156
|
+
logger << "Timeout, so trying SIGINT at #{wait_thread[:pid]}=#{full_script}"
|
144
157
|
|
145
158
|
log_copy = Thread.new do
|
146
159
|
pout.each_line { |l| logger << l }
|
@@ -167,7 +180,7 @@ module ParallelCucumber
|
|
167
180
|
end
|
168
181
|
|
169
182
|
logger << "About to reap root #{pid}"
|
170
|
-
|
183
|
+
wait_thread.value # reap root - everything else should be reaped by init.
|
171
184
|
logger << "Reaped root #{pid}"
|
172
185
|
end
|
173
186
|
end
|
@@ -47,6 +47,13 @@ module ParallelCucumber
|
|
47
47
|
report
|
48
48
|
end
|
49
49
|
|
50
|
+
def unknown_result(tests)
|
51
|
+
res = tests.map do |test|
|
52
|
+
[test.to_sym, {status: ::ParallelCucumber::Status::UNKNOWN}]
|
53
|
+
end
|
54
|
+
res.to_h
|
55
|
+
end
|
56
|
+
|
50
57
|
private
|
51
58
|
|
52
59
|
def dry_run_report(options, args_string)
|
@@ -20,6 +20,7 @@ module ParallelCucumber
|
|
20
20
|
details[:exception_classname] = event.result.exception.class.to_s
|
21
21
|
details[:exception_message] = event.result.exception.message
|
22
22
|
end
|
23
|
+
details[:name] = "#{event.test_case.feature}: #{event.test_case.name}"
|
23
24
|
details[:finish_time] = Time.now.to_i
|
24
25
|
@result[event.test_case.location.to_s] = details
|
25
26
|
end
|
@@ -35,7 +35,7 @@ module ParallelCucumber
|
|
35
35
|
else
|
36
36
|
descendants(root, logger, tree, old_tree, 'kill') do |pid, node|
|
37
37
|
begin
|
38
|
-
logger.warn "
|
38
|
+
logger.warn "Sending signal #{sig} to #{node}"
|
39
39
|
Process.kill(sig, pid.to_i)
|
40
40
|
rescue Errno::ESRCH
|
41
41
|
nil # It's gone already? Hurrah!
|
@@ -44,7 +44,7 @@ module ParallelCucumber
|
|
44
44
|
end
|
45
45
|
# Let's kill pid unconditionally: descendants will go astray once reparented.
|
46
46
|
begin
|
47
|
-
logger.warn "
|
47
|
+
logger.warn "Sending signal #{sig} to root process #{root} just in case"
|
48
48
|
Process.kill(sig, root.to_i)
|
49
49
|
rescue Errno::ESRCH
|
50
50
|
nil # It's gone already? Hurrah!
|
@@ -1,12 +1,19 @@
|
|
1
1
|
module ParallelCucumber
|
2
2
|
class Hooks
|
3
|
-
@
|
4
|
-
@
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
3
|
+
@worker_health_check ||= []
|
4
|
+
@before_batch_hooks ||= []
|
5
|
+
@after_batch_hooks ||= []
|
6
|
+
@before_workers ||= []
|
7
|
+
@after_workers ||= []
|
8
|
+
@on_batch_error ||= []
|
9
|
+
@on_dry_run_error ||= []
|
8
10
|
|
9
11
|
class << self
|
12
|
+
def register_worker_health_check(proc)
|
13
|
+
raise(ArgumentError, 'Please provide a valid callback') unless proc.respond_to?(:call)
|
14
|
+
@worker_health_check << proc
|
15
|
+
end
|
16
|
+
|
10
17
|
def register_before_batch(proc)
|
11
18
|
raise(ArgumentError, 'Please provide a valid callback') unless proc.respond_to?(:call)
|
12
19
|
@before_batch_hooks << proc
|
@@ -32,6 +39,17 @@ module ParallelCucumber
|
|
32
39
|
@on_batch_error << proc
|
33
40
|
end
|
34
41
|
|
42
|
+
def register_on_dry_run_error(proc)
|
43
|
+
raise(ArgumentError, 'Please provide a valid callback') unless proc.respond_to?(:call)
|
44
|
+
@on_dry_run_error << proc
|
45
|
+
end
|
46
|
+
|
47
|
+
def fire_worker_health_check(*args)
|
48
|
+
@worker_health_check.each do |hook|
|
49
|
+
hook.call(*args)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
35
53
|
def fire_before_batch_hooks(*args)
|
36
54
|
@before_batch_hooks.each do |hook|
|
37
55
|
hook.call(*args)
|
@@ -61,6 +79,12 @@ module ParallelCucumber
|
|
61
79
|
hook.call(*args)
|
62
80
|
end
|
63
81
|
end
|
82
|
+
|
83
|
+
def fire_on_dry_run_error(error)
|
84
|
+
@on_dry_run_error.each do |hook|
|
85
|
+
hook.call(error)
|
86
|
+
end
|
87
|
+
end
|
64
88
|
end
|
65
89
|
end
|
66
90
|
end
|
@@ -30,8 +30,12 @@ module ParallelCucumber
|
|
30
30
|
exit(1)
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
begin
|
34
|
+
all_tests = Helper::Cucumber.selected_tests(@options[:cucumber_options], @options[:cucumber_args])
|
35
|
+
rescue StandardError => error
|
36
|
+
Hooks.fire_on_dry_run_error(error)
|
37
|
+
raise error
|
38
|
+
end
|
35
39
|
if all_tests.empty?
|
36
40
|
@logger.info('There is no tests to run, exiting...')
|
37
41
|
exit(0)
|
@@ -10,11 +10,9 @@ module ParallelCucumber
|
|
10
10
|
@group_by = options[:group_by]
|
11
11
|
@batch_timeout = options[:batch_timeout]
|
12
12
|
@batch_error_timeout = options[:batch_error_timeout]
|
13
|
-
@precheck_timeout = options[:precheck_timeout]
|
14
13
|
@setup_timeout = options[:setup_timeout]
|
15
14
|
@cucumber_options = options[:cucumber_options]
|
16
15
|
@test_command = options[:test_command]
|
17
|
-
@pre_check = options[:pre_check]
|
18
16
|
@index = index
|
19
17
|
@name = "W#{@index}"
|
20
18
|
@setup_worker = options[:setup_worker]
|
@@ -99,12 +97,7 @@ module ParallelCucumber
|
|
99
97
|
job = @jobs_queue.pop(false)
|
100
98
|
case job.type
|
101
99
|
when Job::PRECHECK
|
102
|
-
|
103
|
-
if (m = precmd.match(/precmd:retry-after-(\d+)-seconds/))
|
104
|
-
@manager.inform_idle(@name)
|
105
|
-
sleep(1 + m[1].to_i)
|
106
|
-
next
|
107
|
-
end
|
100
|
+
Hooks.fire_worker_health_check(env)
|
108
101
|
@manager.inform_healthy(@name)
|
109
102
|
when Job::RUN_TESTS
|
110
103
|
run_batch(env, results, running_total, job.details)
|
@@ -161,18 +154,6 @@ module ParallelCucumber
|
|
161
154
|
@logger.update_into(@stdout_logger)
|
162
155
|
end
|
163
156
|
|
164
|
-
def precheck(env)
|
165
|
-
return 'default no-op pre_check' unless @pre_check
|
166
|
-
begin
|
167
|
-
return Helper::Command.exec_command(
|
168
|
-
env, 'precheck', @pre_check, @logger, @log_decoration, timeout: @precheck_timeout, capture: true
|
169
|
-
)
|
170
|
-
rescue
|
171
|
-
@logger.error('Pre-check failed: quitting immediately')
|
172
|
-
raise 'Pre-check failed: quitting immediately'
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
157
|
def running_totals(batch_results, running_total)
|
177
158
|
batch_info = Status.constants.map do |status|
|
178
159
|
status = Status.const_get(status)
|
@@ -220,7 +201,8 @@ module ParallelCucumber
|
|
220
201
|
begin
|
221
202
|
ParallelCucumber::Helper::Command.exec_command(
|
222
203
|
batch_env, 'batch', mapped_batch_cmd, @logger, @log_decoration,
|
223
|
-
timeout: @batch_timeout, return_script_error: true
|
204
|
+
timeout: @batch_timeout, capture: true, return_script_error: true,
|
205
|
+
return_on_timeout: true, collect_stacktrace: true
|
224
206
|
)
|
225
207
|
rescue => e
|
226
208
|
@logger << "ERROR #{e} #{e.backtrace.first(5)}"
|
@@ -232,7 +214,7 @@ module ParallelCucumber
|
|
232
214
|
@logger.warn("There was exception in on_batch_error hook #{exc.message} \n #{trace}")
|
233
215
|
end
|
234
216
|
|
235
|
-
return
|
217
|
+
return Helper::Cucumber.unknown_result(tests)
|
236
218
|
end
|
237
219
|
parse_results(test_state, tests)
|
238
220
|
ensure
|
@@ -291,18 +273,18 @@ module ParallelCucumber
|
|
291
273
|
def parse_results(f, tests)
|
292
274
|
unless File.file?(f)
|
293
275
|
@logger.error("Results file does not exist: #{f}")
|
294
|
-
return
|
276
|
+
return Helper::Cucumber.unknown_result(tests)
|
295
277
|
end
|
296
278
|
json_report = File.read(f)
|
297
279
|
if json_report.empty?
|
298
280
|
@logger.error("Results file is empty: #{f}")
|
299
|
-
return
|
281
|
+
return Helper::Cucumber.unknown_result(tests)
|
300
282
|
end
|
301
283
|
Helper::Cucumber.parse_json_report(json_report)
|
302
284
|
rescue => e
|
303
285
|
trace = e.backtrace.join("\n\t").sub("\n\t", ": #{$ERROR_INFO}#{e.class ? " (#{e.class})" : ''}\n\t")
|
304
286
|
@logger.error("Threw: JSON parse of results caused #{trace}")
|
305
|
-
|
287
|
+
Helper::Cucumber.unknown_result(tests)
|
306
288
|
end
|
307
289
|
end
|
308
290
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel_cucumber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Bayandin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 0.73.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 0.73.0
|
83
83
|
description: Our own parallel cucumber with queue and workers
|
84
84
|
email: a.bayandin@gmail.com
|
85
85
|
executables:
|
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: '0'
|
129
129
|
requirements: []
|
130
|
-
rubygems_version: 3.0.
|
130
|
+
rubygems_version: 3.0.3
|
131
131
|
signing_key:
|
132
132
|
specification_version: 4
|
133
133
|
summary: Run cucumber in parallel
|