rspec-core-parallel 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b57c9af852c507ef4696411ab9de26231b9c04d9400fb8cdb48beb99edf4a89
4
- data.tar.gz: ef94f289bf3f6128f124c7bf3c0300a11d435cf0e8a40c2405beaae4b3c274d3
3
+ metadata.gz: 1e45d853c91a7618f7d3e2610761a0a7271ade685db327199de1b3a045ed9609
4
+ data.tar.gz: f652d5b00ce96ef27afbab7d064caaf8ed9cc5541c5fa739708bdd24cf08c5ef
5
5
  SHA512:
6
- metadata.gz: c57a12dc5500fc4578a6ac51bfaa27b68b4f98da09e4297e2857993328ed2b6a9923851caffd14db0cc9a88fd9aecaa30dbdccb9fe44fcc721b48b4885329baa
7
- data.tar.gz: d5b61024b3bc242e08c1c35a0b65feb8877083542f85f33d970a4250e30fcdc0a2f473f097cb0fad9c816e1e393ad54406637d39deef1ed55c1e8ed456273a3a
6
+ metadata.gz: ce28c54e6b455f78bed2682ce55ddc7c79b53ee3913a9ea3c5e91ed13f2b0507baa56130a494feb1bd913a3c05ea30819eb29608ee2aa82b9b314ab5335b6a1b
7
+ data.tar.gz: 2db7c74933f5f617e44027b3687b473395d2c4d93e8277ac13b172e558b6c3304a572ef5f5c81c77acbf26c85e4802b3d1aa3ea9b811b2c67b1c6b20c7cadd4e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0
4
+
5
+ * `before(:run)` and `after(:run)` hooks, which run once per run: in the main
6
+ process around the workers in parallel runs, around the `:suite` hooks in
7
+ sequential runs.
8
+ * SimpleCov merges the coverage of workers that finished more than its
9
+ `merge_timeout` (10 minutes by default) before the slowest one.
10
+
11
+ ## 0.2.1
12
+
13
+ * No deprecation warning with SimpleCov 1.x, which renamed
14
+ `enable_for_subprocesses` to `merge_subprocesses`.
15
+
3
16
  ## 0.2.0
4
17
 
5
18
  * SimpleCov collects the coverage of the workers without any configuration.
data/README.md CHANGED
@@ -83,7 +83,18 @@ RSpec.configure do |config|
83
83
  end
84
84
  ```
85
85
 
86
- **Hooks.** `before(:suite)`, `after(:suite)` and `at_exit` hooks run in every worker.
86
+ **Hooks.** `before(:suite)`, `after(:suite)` and `at_exit` hooks run in every worker. For what all the workers share,
87
+ like starting a service or cleaning it up, use `before(:run)` and `after(:run)`: they run once, in the main process,
88
+ before the workers are forked and after they have exited. In sequential runs they run around the `:suite` hooks.
89
+
90
+ ```ruby
91
+ RSpec.configure do |config|
92
+ config.before(:run) { TestServer.start }
93
+ config.after(:run) { TestServer.stop }
94
+ end
95
+ ```
96
+
97
+ When a `before(:run)` hook fails, no example runs, but the `after(:run)` hooks still do.
87
98
 
88
99
  ## Code coverage
89
100
 
@@ -107,8 +107,74 @@ module RSpec
107
107
  Parallel.supported? ? Parallel.default_worker_count : 1
108
108
  end
109
109
 
110
+ # `before(:run)` and `after(:run)` hooks run once per run: around the
111
+ # `:suite` hooks in sequential runs, and in the main process around
112
+ # the workers in parallel runs, where `:suite` hooks run in every
113
+ # worker. Use them for what all the workers share, like starting a
114
+ # service or cleaning it up.
115
+ def before(scope=nil, *meta, &block)
116
+ return super unless scope == :run
117
+
118
+ run_hooks(:before) << Hooks::BeforeHook.new(block, {})
119
+ end
120
+ alias_method :append_before, :before
121
+
122
+ def prepend_before(scope=nil, *meta, &block)
123
+ return super unless scope == :run
124
+
125
+ run_hooks(:before).unshift Hooks::BeforeHook.new(block, {})
126
+ end
127
+
128
+ def after(scope=nil, *meta, &block)
129
+ return super unless scope == :run
130
+
131
+ run_hooks(:after).unshift Hooks::AfterHook.new(block, {})
132
+ end
133
+ alias_method :prepend_after, :after
134
+
135
+ def append_after(scope=nil, *meta, &block)
136
+ return super unless scope == :run
137
+
138
+ run_hooks(:after) << Hooks::AfterHook.new(block, {})
139
+ end
140
+
141
+ def with_suite_hooks
142
+ return super if parallel_worker_number
143
+
144
+ with_run_hooks { super }
145
+ end
146
+
147
+ # @private
148
+ #
149
+ # Examples are not run when a `before(:run)` hook fails, but all the
150
+ # `after(:run)` hooks are, so that everything started is stopped.
151
+ def with_run_hooks
152
+ return yield if dry_run?
153
+
154
+ begin
155
+ run_run_hooks('a `before(:run)` hook', run_hooks(:before), :stop_on_failure) ? yield : false
156
+ ensure
157
+ run_run_hooks('an `after(:run)` hook', run_hooks(:after))
158
+ end
159
+ end
160
+
110
161
  private
111
162
 
163
+ def run_hooks(position)
164
+ (@run_hooks ||= { :before => [], :after => [] })[position]
165
+ end
166
+
167
+ def run_run_hooks(description, hooks, stop_on_failure=false)
168
+ context = SuiteHookContext.new(description, reporter)
169
+ hooks.each do |hook|
170
+ hook.run(context)
171
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
172
+ context.set_exception(e)
173
+ return false if stop_on_failure
174
+ end
175
+ true
176
+ end
177
+
112
178
  # rspec-core runs the default path (`spec`) when no files are given
113
179
  # only when its command is `rspec`.
114
180
  def command
@@ -148,7 +214,7 @@ module RSpec
148
214
 
149
215
  examples_count = @world.example_count(example_groups)
150
216
  examples_passed = @configuration.reporter.report(examples_count) do |reporter|
151
- Parallel.run(@configuration, @world, parallel_units, reporter)
217
+ @configuration.with_run_hooks { Parallel.run(@configuration, @world, parallel_units, reporter) }
152
218
  end
153
219
 
154
220
  exit_code(examples_passed)
@@ -16,6 +16,8 @@ module RSpec
16
16
  # `TEST_ENV_NUMBER`), so workers finishing early checked the coverage
17
17
  # collected so far and printed false "below minimum coverage"
18
18
  # warnings. The main process exits after all the workers.
19
+ # * extends SimpleCov's `merge_timeout` by the time the workers ran, so
20
+ # that the main process merges the results of all of them.
19
21
  #
20
22
  # @private
21
23
  module SimpleCovIntegration
@@ -28,11 +30,19 @@ module RSpec
28
30
 
29
31
  def self.before_fork
30
32
  @command_name = nil
33
+ @forked_at = nil
31
34
  return unless defined?(::SimpleCov) && defined?(::Coverage.running?) && ::Coverage.running?
35
+
36
+ @forked_at = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
32
37
  return if ::SimpleCov.enabled_for_subprocesses?
33
38
 
34
39
  @command_name = ::SimpleCov.command_name
35
- ::SimpleCov.enable_for_subprocesses true
40
+ # SimpleCov 1.x renamed `enable_for_subprocesses`, deprecating it.
41
+ if ::SimpleCov.respond_to?(:merge_subprocesses)
42
+ ::SimpleCov.merge_subprocesses true
43
+ else
44
+ ::SimpleCov.enable_for_subprocesses true
45
+ end
36
46
  require 'simplecov/process'
37
47
  end
38
48
 
@@ -42,6 +52,15 @@ module RSpec
42
52
  ::SimpleCov.command_name "#{@command_name} (worker #{worker_number})" if @command_name
43
53
  ::SimpleCov.singleton_class.__send__(:prepend, NotFinalResultProcess)
44
54
  end
55
+
56
+ # SimpleCov merges only results younger than `merge_timeout`: those of
57
+ # workers finished long before the slowest one would be left out.
58
+ def self.after_workers
59
+ return unless @forked_at && ::SimpleCov.respond_to?(:merge_timeout)
60
+
61
+ workers_time = (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @forked_at).ceil
62
+ ::SimpleCov.merge_timeout(::SimpleCov.merge_timeout + workers_time)
63
+ end
45
64
  end
46
65
  end
47
66
  end
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Parallel
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
6
6
  end
7
7
  end
@@ -51,6 +51,7 @@ module RSpec
51
51
  def self.run(configuration, world, units, reporter)
52
52
  worker_count = [configuration.parallel_workers.to_i, units.size].min
53
53
  passed = Coordinator.new(configuration, world, worker_count).run(units, reporter)
54
+ SimpleCovIntegration.after_workers
54
55
  persist_run_times(configuration, world)
55
56
  passed
56
57
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-core-parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Rodi