parallel_cucumber 0.2.17 → 0.2.22

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.
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