parallel_cucumber 0.2.17 → 0.2.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5664f82c63144d99bec9dc1880905601d0de45b2431b929eee77c0c4abb4521f
4
- data.tar.gz: 9c5fce5710b7a36270c5f84431bc32195bf54a37779380ea584e04f892b8e616
3
+ metadata.gz: 4d312aab611528ffc08d935c5871ba120f18e27364de8ab2bd5ea42183e4ce46
4
+ data.tar.gz: 9c5f960b08d8b2f03fc937387bb735ca447791b49381c803f9d34811eb35ee9e
5
5
  SHA512:
6
- metadata.gz: c51f9ebe8c466e9e31936ddf59bc1944f5ddab128e317d4185b4047d7d7c2f63f091c242556ac2185bd67bbd3de7145fe31fbb3fc51239e56b1b046b3412087e
7
- data.tar.gz: bac0d600b9e52aacc815a7ad2e3138470c5efafa2aad96d4c94ba82bae7d82df2bdd48ce21b2b78b09c98045f1f40e3e13b760ef371a8f16babd7bfdeef180c4
6
+ metadata.gz: c79e25152a7f1f991b8dbc407904b8421e0eca3cc8fc45cf2217d5f0e3d39fff716310b38f77380b0d91c46bc3819002a37b735dcb8bcd0c894628827bdf4a8c
7
+ data.tar.gz: f4a846cf322989b8c60d95b23e3b744408c73729aecb8f12919479c21c636f35868060aaa7afb20e1d2b54472df06f022f22529ac97f874cae8d0741c804518a
@@ -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
@@ -26,25 +26,32 @@ module ParallelCucumber
26
26
 
27
27
  def parse_json_report(json_report)
28
28
  report = JSON.parse(json_report, symbolize_names: true)
29
- report.map do |scenario, cucumber_status|
30
- status = case cucumber_status
31
- when 'failed'
32
- Status::FAILED
33
- when 'passed'
34
- Status::PASSED
35
- when 'pending'
36
- Status::PENDING
37
- when 'skipped'
38
- Status::SKIPPED
39
- when 'undefined'
40
- Status::UNDEFINED
41
- when 'unknown'
42
- Status::UNKNOWN
43
- else
44
- Status::UNKNOWN
45
- end
46
- [scenario, status]
47
- end.to_h
29
+ report.each do |scenario, details|
30
+ report[scenario][:status] = case details[:status]
31
+ when 'failed'
32
+ Status::FAILED
33
+ when 'passed'
34
+ Status::PASSED
35
+ when 'pending'
36
+ Status::PENDING
37
+ when 'skipped'
38
+ Status::SKIPPED
39
+ when 'undefined'
40
+ Status::UNDEFINED
41
+ when 'unknown'
42
+ Status::UNKNOWN
43
+ else
44
+ Status::UNKNOWN
45
+ end
46
+ end
47
+ report
48
+ end
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
48
55
  end
49
56
 
50
57
  private
@@ -57,7 +64,7 @@ module ParallelCucumber
57
64
  options = remove_strict_flag(options)
58
65
  content = nil
59
66
 
60
- Tempfile.open(%w(dry-run .json)) do |f|
67
+ Tempfile.open(%w[dry-run .json]) do |f|
61
68
  dry_run_options = "--dry-run --format ParallelCucumber::Helper::Cucumber::JsonStatusFormatter --out #{f.path}"
62
69
 
63
70
  cmd = "cucumber #{options} #{dry_run_options} #{args_string}"
@@ -15,7 +15,13 @@ module ParallelCucumber
15
15
  end
16
16
 
17
17
  def on_after_test_case(event)
18
- @result[event.test_case.location.to_s] = event.result.to_sym
18
+ details = {status: event.result.to_sym}
19
+ if event.result.respond_to?(:exception)
20
+ details[:exception_classname] = event.result.exception.class.to_s
21
+ details[:exception_message] = event.result.exception.message
22
+ end
23
+ details[:finish_time] = Time.now.to_i
24
+ @result[event.test_case.location.to_s] = details
19
25
  end
20
26
 
21
27
  def on_finished_testing(*)
@@ -1,12 +1,19 @@
1
1
  module ParallelCucumber
2
2
  class Hooks
3
- @before_batch_hooks ||= []
4
- @after_batch_hooks ||= []
5
- @before_workers ||= []
6
- @after_workers ||= []
7
- @on_batch_error ||= []
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
- all_tests = Helper::Cucumber.selected_tests(@options[:cucumber_options], @options[:cucumber_args])
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)
@@ -98,7 +102,7 @@ module ParallelCucumber
98
102
 
99
103
  status_totals = Status.constants.map do |status|
100
104
  status = Status.const_get(status)
101
- tests_with_status = results.select { |_t, s| s == status }.keys
105
+ tests_with_status = results.select { |_t, s| s[:status] == status }.keys
102
106
  [status, tests_with_status]
103
107
  end.to_h
104
108
 
@@ -1,3 +1,3 @@
1
1
  module ParallelCucumber
2
- VERSION = '0.2.17'.freeze
2
+ VERSION = '0.2.22'.freeze
3
3
  end
@@ -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
- precmd = precheck(env)
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,22 +154,10 @@ 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)
179
- [status, batch_results.select { |_t, s| s == status }.keys]
160
+ [status, batch_results.select { |_t, s| s[:status] == status }.keys]
180
161
  end.to_h
181
162
  batch_info.each do |s, tt|
182
163
  @logger.info("#{s.to_s.upcase} #{tt.count} tests: #{tt.join(' ')}") unless tt.empty?
@@ -191,7 +172,7 @@ module ParallelCucumber
191
172
  test_syms = tests.map(&:to_sym)
192
173
  unrun = test_syms - batch_keys
193
174
  surfeit = batch_keys - test_syms
194
- unrun.each { |test| batch_results[test] = Status::UNKNOWN }
175
+ unrun.each { |test| batch_results[test][:status] = Status::UNKNOWN }
195
176
  surfeit.each { |test| batch_results.delete(test) }
196
177
  @logger.error("Did not run #{unrun.count}/#{tests.count}: #{unrun.join(' ')}") unless unrun.empty?
197
178
  @logger.error("Extraneous runs (#{surfeit.count}): #{surfeit.join(' ')}") unless surfeit.empty?
@@ -232,7 +213,7 @@ module ParallelCucumber
232
213
  @logger.warn("There was exception in on_batch_error hook #{exc.message} \n #{trace}")
233
214
  end
234
215
 
235
- return tests.map { |t| [t, ::ParallelCucumber::Status::UNKNOWN] }.to_h
216
+ return Helper::Cucumber.unknown_result(tests)
236
217
  end
237
218
  parse_results(test_state, tests)
238
219
  ensure
@@ -291,18 +272,18 @@ module ParallelCucumber
291
272
  def parse_results(f, tests)
292
273
  unless File.file?(f)
293
274
  @logger.error("Results file does not exist: #{f}")
294
- return tests.map { |t| [t, ::ParallelCucumber::Status::UNKNOWN] }.to_h
275
+ return Helper::Cucumber.unknown_result(tests)
295
276
  end
296
277
  json_report = File.read(f)
297
278
  if json_report.empty?
298
279
  @logger.error("Results file is empty: #{f}")
299
- return tests.map { |t| [t, ::ParallelCucumber::Status::UNKNOWN] }.to_h
280
+ return Helper::Cucumber.unknown_result(tests)
300
281
  end
301
282
  Helper::Cucumber.parse_json_report(json_report)
302
283
  rescue => e
303
284
  trace = e.backtrace.join("\n\t").sub("\n\t", ": #{$ERROR_INFO}#{e.class ? " (#{e.class})" : ''}\n\t")
304
285
  @logger.error("Threw: JSON parse of results caused #{trace}")
305
- tests.map { |t| [t, ::ParallelCucumber::Status::UNKNOWN] }.to_h
286
+ Helper::Cucumber.unknown_result(tests)
306
287
  end
307
288
  end
308
289
  end
@@ -39,7 +39,7 @@ module ParallelCucumber
39
39
  def create_workers(number_of_workers)
40
40
  number_of_workers.times do |index|
41
41
  @workers["W#{index}"] =
42
- ParallelCucumber::Worker.new(options: @options, index: index, stdout_logger: @logger, manager: self)
42
+ ParallelCucumber::Worker.new(options: @options, index: index, stdout_logger: @logger, manager: self)
43
43
  end
44
44
  end
45
45
 
@@ -51,11 +51,11 @@ module ParallelCucumber
51
51
  give_job_to_healthy_worker
52
52
  elsif any_worker_busy?
53
53
  kill_surplus_workers
54
- sleep 0.5
55
54
  else
56
55
  kill_all_workers
57
56
  break
58
57
  end
58
+ sleep 0.5
59
59
  end
60
60
  end
61
61
  end
@@ -67,10 +67,15 @@ module ParallelCucumber
67
67
  puts "Starting W#{index}"
68
68
  @workers["W#{index}"].start(env_for_worker(@options[:env_variables], index))
69
69
  end
70
- @results.inject(:merge) # Returns hash of file:line to statuses + :worker-index to summary.
70
+ @results.inject do |seed, result|
71
+ seed.merge(result) do |_key, oldval, newval|
72
+ (newval[:finish_time] > oldval[:finish_time]) ? newval : oldval
73
+ end
74
+ end
71
75
  end
72
76
 
73
77
  def kill_all_workers
78
+ @logger.info('=== Killing All Workers')
74
79
  @workers.values.each { |w| w.assign_job(Job.new(Job::DIE)) }
75
80
  end
76
81
 
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.17
4
+ version: 0.2.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Bayandin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-23 00:00:00.000000000 Z
11
+ date: 2020-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -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.4
130
+ rubygems_version: 3.0.3
131
131
  signing_key:
132
132
  specification_version: 4
133
133
  summary: Run cucumber in parallel