parallel_rspec_simplecov 0.3.0 → 1.0.0.rc1

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: 3a942644939bc97f3b7a8567c0d0ee07cd78095366503aa10400dda8d707f0fc
4
- data.tar.gz: 77581e6f6239a62a28989581d5528ad0253b1333c0547d9efedc61111a05f97c
3
+ metadata.gz: 9bdcdacea3afc1313b6a67c49dc222909b877e2270a5e450f5da29f6bba7aba3
4
+ data.tar.gz: 4413ab01734c4395b3aab98500015706e62c67cd1598a15489f869417dec52df
5
5
  SHA512:
6
- metadata.gz: 9bbfaba6a75af9d81dbba64d6eefe40a94d0561b4efc83ba981d63b4dae41c8b421e923b8642b871213706c1a8d7fca524bb86082ddfea3548dd3be4d550b361
7
- data.tar.gz: e6ca0cb5329fe63100ba78a29e6bd2ce751e02859f708afef0aa9b95d0e46e019bf5483b310bdab2dca1332cc88c05b23e4c30ffe48636d25a38a39ed8767947
6
+ metadata.gz: f0825595a26b144bda243ea0699c740de6c03914ce5d234786d268598f69469cee31cda3af357226d9176d065a0096705dbb9bfd380eb8039e8a2ec92b569b49
7
+ data.tar.gz: d526f3501070e33f50789c319e4715706fd0739fd5b6e74ee453d582cf4291de4dcf6a74ce3bc94184fcf8583e05d262f185bef8c371e68ebb86a27a943855f0
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/README.md CHANGED
@@ -1,39 +1,33 @@
1
- # ParallelRSpec::Simplecov
1
+ # ParallelRSpec::SimpleCov
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ A very small library for collecting SimpleCov coverage from RSpec suites run in parallel via [parallel_rspec](https://github.com/willbryant/parallel_rspec).
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/parallel_rspec_simplecov`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ SimpleCov doesn't merge coverage across `parallel_rspec`'s forked workers by default; this gem registers an `after_fork` hook so each worker writes its own resultset, then collates them in `after(:suite)`.
6
6
 
7
7
  ## Installation
8
8
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
- Install the gem and add to the application's Gemfile by executing:
12
-
13
- ```bash
14
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
15
- ```
16
-
17
- If bundler is not being used to manage dependencies, install the gem by executing:
18
-
19
9
  ```bash
20
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
10
+ bundle add parallel_rspec_simplecov
21
11
  ```
22
12
 
23
13
  ## Usage
24
14
 
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
- ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/parallel_rspec_simplecov.
15
+ Replace your call (in `spec_helper.rb`, for example) to `SimpleCov.start` with a call to `ParallelRSpec::SimpleCov.start`. It accepts the same positional `profile` argument and configuration block as `SimpleCov.start`, plus a `formatters:` keyword listing the formatters to apply to the *merged* result.
16
+
17
+ ```ruby
18
+ ParallelRSpec::SimpleCov.start(
19
+ 'rails',
20
+ formatters: [
21
+ SimpleCov::Formatter::HTMLFormatter,
22
+ SimpleCov::Formatter::CoberturaFormatter,
23
+ ]
24
+ ) do
25
+ enable_coverage :branch
26
+ add_filter '/spec/'
27
+ add_filter '/config/'
28
+ end
29
+ ```
36
30
 
37
- ## License
31
+ ## Output
38
32
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
33
+ Per-worker resultsets land in `coverage/rspec_N/`; the merged result and any formatter output (HTML, Cobertura, …) end up at the top level of `coverage/`.
data/Rakefile CHANGED
@@ -1,4 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- task default: %i[]
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -5,14 +5,32 @@ require "parallel_rspec/config"
5
5
  module ParallelRSpec::SimpleCov
6
6
  @simplecov_enabled = false
7
7
  @simplecov_base_dir = nil
8
- @simplecov_formatters = nil
8
+ @simplecov_formatters = []
9
9
 
10
+ # Returns true once {.start} has been called in this process.
11
+ #
12
+ # @return [Boolean]
10
13
  def self.simplecov_enabled?
11
14
  @simplecov_enabled
12
15
  end
13
16
 
17
+ # Configure SimpleCov to merge coverage across `parallel_rspec` workers.
18
+ #
19
+ # Call this in place of `SimpleCov.start` from your `spec_helper.rb`. It
20
+ # starts SimpleCov on the server process, registers an `after_fork` hook
21
+ # so each worker writes its own resultset under `coverage/rspec_N/`, and
22
+ # registers an `after(:suite)` hook to collate everything into a merged
23
+ # report at the end of the run.
24
+ #
25
+ # Idempotent: subsequent calls are no-ops.
26
+ #
27
+ # @param profile [String, nil] SimpleCov profile name, passed through to `SimpleCov.start`.
28
+ # @param formatters [Array<SimpleCov::Formatter>, nil] formatters to apply to the merged result. Accepts formatter classes or instances. When more than one is given they are wrapped in a `MultiFormatter`. When omitted, SimpleCov's default formatter is used.
29
+ # @yield SimpleCov configuration block (e.g. `add_filter`, `enable_coverage :branch`), passed through to `SimpleCov.start`.
30
+ # @return [void]
14
31
  def self.start(profile = nil, formatters: nil, &block)
15
- puts "SimpleCov.start"
32
+ return if @simplecov_enabled
33
+
16
34
  ::SimpleCov.enable_for_subprocesses true
17
35
 
18
36
  base_dir = ::SimpleCov.coverage_dir
@@ -48,10 +66,16 @@ module ParallelRSpec::SimpleCov
48
66
  start_simplecov.call("RSpec Server", File.join(base_dir, "rspec_server"))
49
67
 
50
68
  @simplecov_base_dir = base_dir
51
- @simplecov_formatters = formatters
69
+ @simplecov_formatters = Array(formatters)
52
70
  @simplecov_enabled = true
53
71
  end
54
72
 
73
+ # Merge per-worker resultsets into a single report. Called automatically
74
+ # from the `after(:suite)` hook installed by {.start} — not intended to
75
+ # be called directly.
76
+ #
77
+ # @api private
78
+ # @return [void]
55
79
  def self.collate!
56
80
  base_dir = @simplecov_base_dir || ::SimpleCov.coverage_dir
57
81
 
@@ -68,19 +92,18 @@ module ParallelRSpec::SimpleCov
68
92
  end
69
93
 
70
94
  collate_formatter =
71
- case (@simplecov_formatters || []).length
95
+ case @simplecov_formatters.length
72
96
  when 0 then nil
73
97
  when 1 then @simplecov_formatters.first
74
98
  else ::SimpleCov::Formatter::MultiFormatter.new(@simplecov_formatters)
75
99
  end
76
100
 
77
- puts "Collating #{resultsets.size} SimpleCov resultset(s)..."
78
-
79
101
  ::SimpleCov.collate(resultsets) do
80
102
  coverage_dir base_dir
81
103
  formatter collate_formatter if collate_formatter
82
104
  end
83
105
  rescue => e
84
106
  warn "[parallel_rspec] simplecov collation failed: #{e.class}: #{e.message}"
107
+ warn e.backtrace.first(5).join("\n") if e.backtrace
85
108
  end
86
109
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ParallelRSpec
4
4
  module SimpleCov
5
- VERSION = "0.3.0"
5
+ VERSION = "1.0.0.rc1"
6
6
  end
7
7
  end
@@ -1,3 +1,9 @@
1
- module ParallelRSpec::Simplecov
2
- VERSION: String
1
+ module ParallelRSpec
2
+ module SimpleCov
3
+ VERSION: String
4
+
5
+ def self.simplecov_enabled?: () -> bool
6
+ def self.start: (?String? profile, ?formatters: Array[untyped]?) ?{ () -> void } -> void
7
+ def self.collate!: () -> void
8
+ end
3
9
  end
@@ -0,0 +1,119 @@
1
+ RSpec.describe ParallelRSpec::SimpleCov do
2
+ before do
3
+ described_class.instance_variable_set(:@simplecov_enabled, false)
4
+ described_class.instance_variable_set(:@simplecov_base_dir, nil)
5
+ described_class.instance_variable_set(:@simplecov_formatters, [])
6
+ end
7
+
8
+ describe ".simplecov_enabled?" do
9
+ it "is false before start is called" do
10
+ expect(described_class.simplecov_enabled?).to be false
11
+ end
12
+ end
13
+
14
+ describe ".start" do
15
+ let(:after_fork_callbacks) { [] }
16
+ let(:after_suite_hooks) { [] }
17
+
18
+ before do
19
+ allow(::SimpleCov).to receive(:enable_for_subprocesses)
20
+ allow(::SimpleCov).to receive(:coverage_dir).and_return("coverage")
21
+ allow(::SimpleCov).to receive(:command_name)
22
+ allow(::SimpleCov).to receive(:start)
23
+ allow(::SimpleCov).to receive(:print_error_status=)
24
+ allow(::SimpleCov).to receive(:formatter)
25
+ allow(::SimpleCov).to receive(:minimum_coverage)
26
+
27
+ allow(ParallelRSpec::Config).to receive(:after_fork) do |&block|
28
+ after_fork_callbacks << block
29
+ end
30
+ allow(RSpec.configuration).to receive(:after).with(:suite) do |&block|
31
+ after_suite_hooks << block
32
+ end
33
+ end
34
+
35
+ it "marks simplecov as enabled" do
36
+ described_class.start
37
+ expect(described_class).to be_simplecov_enabled
38
+ end
39
+
40
+ it "registers exactly one after_fork callback" do
41
+ described_class.start
42
+ expect(after_fork_callbacks.size).to eq(1)
43
+ end
44
+
45
+ it "registers exactly one after(:suite) hook" do
46
+ described_class.start
47
+ expect(after_suite_hooks.size).to eq(1)
48
+ end
49
+
50
+ it "is idempotent — repeated calls do not re-register hooks" do
51
+ described_class.start
52
+ described_class.start
53
+ described_class.start
54
+ expect(after_fork_callbacks.size).to eq(1)
55
+ expect(after_suite_hooks.size).to eq(1)
56
+ end
57
+
58
+ describe "formatter normalization" do
59
+ it "treats nil as an empty array" do
60
+ described_class.start
61
+ expect(described_class.instance_variable_get(:@simplecov_formatters)).to eq([])
62
+ end
63
+
64
+ it "wraps a single formatter in an array" do
65
+ formatter = double("formatter")
66
+ described_class.start(formatters: formatter)
67
+ expect(described_class.instance_variable_get(:@simplecov_formatters)).to eq([formatter])
68
+ end
69
+
70
+ it "preserves an array of formatters" do
71
+ formatters = [double("a"), double("b")]
72
+ described_class.start(formatters: formatters)
73
+ expect(described_class.instance_variable_get(:@simplecov_formatters)).to eq(formatters)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe ".collate!" do
79
+ let(:base_dir) { Dir.mktmpdir("parallel_rspec_simplecov_spec") }
80
+
81
+ before do
82
+ described_class.instance_variable_set(:@simplecov_base_dir, base_dir)
83
+ allow(::SimpleCov).to receive(:result).and_return(instance_double(::SimpleCov::Result, format!: nil))
84
+ end
85
+
86
+ after do
87
+ FileUtils.remove_entry(base_dir)
88
+ end
89
+
90
+ context "when no worker resultsets exist" do
91
+ it "warns and skips collation" do
92
+ allow(::SimpleCov).to receive(:collate)
93
+ expect { described_class.collate! }.to output(/no SimpleCov resultsets found/).to_stderr
94
+ expect(::SimpleCov).not_to have_received(:collate)
95
+ end
96
+ end
97
+
98
+ context "when worker resultsets exist" do
99
+ before do
100
+ ["rspec_1", "rspec_2"].each do |dir|
101
+ FileUtils.mkdir_p(File.join(base_dir, dir))
102
+ File.write(File.join(base_dir, dir, ".resultset.json"), "{}")
103
+ end
104
+ end
105
+
106
+ it "calls SimpleCov.collate with the discovered resultsets" do
107
+ captured_paths = nil
108
+ allow(::SimpleCov).to receive(:collate) { |paths, &_block| captured_paths = paths }
109
+
110
+ described_class.collate!
111
+
112
+ expect(captured_paths).to match_array([
113
+ File.join(base_dir, "rspec_1", ".resultset.json"),
114
+ File.join(base_dir, "rspec_2", ".resultset.json"),
115
+ ])
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,8 @@
1
+ require "parallel_rspec_simplecov"
2
+ require "fileutils"
3
+ require "tmpdir"
4
+
5
+ RSpec.configure do |config|
6
+ config.disable_monkey_patching!
7
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
8
+ end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_rspec_simplecov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Anderson
8
- bindir: exe
8
+ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 3.1.0
32
+ version: '3.1'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 3.1.0
39
+ version: '3.1'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: simplecov
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -57,6 +57,7 @@ executables: []
57
57
  extensions: []
58
58
  extra_rdoc_files: []
59
59
  files:
60
+ - ".rspec"
60
61
  - CHANGELOG.md
61
62
  - LICENSE.txt
62
63
  - README.md
@@ -65,6 +66,8 @@ files:
65
66
  - lib/parallel_rspec_simplecov/simplecov.rb
66
67
  - lib/parallel_rspec_simplecov/version.rb
67
68
  - sig/parallel_rspec_simplecov.rbs
69
+ - spec/parallel_rspec_simplecov_spec.rb
70
+ - spec/spec_helper.rb
68
71
  homepage: https://github.com/bagedevimo/parallel_rspec_simplecov
69
72
  licenses:
70
73
  - MIT
@@ -80,7 +83,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
83
  requirements:
81
84
  - - ">="
82
85
  - !ruby/object:Gem::Version
83
- version: 3.4.0
86
+ version: 3.2.0
84
87
  required_rubygems_version: !ruby/object:Gem::Requirement
85
88
  requirements:
86
89
  - - ">="