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 +4 -4
- data/.rspec +3 -0
- data/README.md +21 -27
- data/Rakefile +5 -1
- data/lib/parallel_rspec_simplecov/simplecov.rb +29 -6
- data/lib/parallel_rspec_simplecov/version.rb +1 -1
- data/sig/parallel_rspec_simplecov.rbs +8 -2
- data/spec/parallel_rspec_simplecov_spec.rb +119 -0
- data/spec/spec_helper.rb +8 -0
- metadata +8 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bdcdacea3afc1313b6a67c49dc222909b877e2270a5e450f5da29f6bba7aba3
|
|
4
|
+
data.tar.gz: 4413ab01734c4395b3aab98500015706e62c67cd1598a15489f869417dec52df
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f0825595a26b144bda243ea0699c740de6c03914ce5d234786d268598f69469cee31cda3af357226d9176d065a0096705dbb9bfd380eb8039e8a2ec92b569b49
|
|
7
|
+
data.tar.gz: d526f3501070e33f50789c319e4715706fd0739fd5b6e74ee453d582cf4291de4dcf6a74ce3bc94184fcf8583e05d262f185bef8c371e68ebb86a27a943855f0
|
data/.rspec
ADDED
data/README.md
CHANGED
|
@@ -1,39 +1,33 @@
|
|
|
1
|
-
# ParallelRSpec::
|
|
1
|
+
# ParallelRSpec::SimpleCov
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10
|
+
bundle add parallel_rspec_simplecov
|
|
21
11
|
```
|
|
22
12
|
|
|
23
13
|
## Usage
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
##
|
|
31
|
+
## Output
|
|
38
32
|
|
|
39
|
-
|
|
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
|
@@ -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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
module ParallelRSpec
|
|
2
|
-
|
|
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
|
data/spec/spec_helper.rb
ADDED
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.
|
|
4
|
+
version: 1.0.0.rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben Anderson
|
|
8
|
-
bindir:
|
|
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
|
|
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
|
|
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.
|
|
86
|
+
version: 3.2.0
|
|
84
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
88
|
requirements:
|
|
86
89
|
- - ">="
|