coverband 6.0.2 → 6.0.3.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/main.yml +2 -3
- data/.standard.yml +1 -1
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +3 -2
- data/Rakefile +1 -1
- data/changes.md +1 -1
- data/coverband.gemspec +3 -3
- data/lib/coverband/adapters/base.rb +10 -10
- data/lib/coverband/adapters/file_store.rb +1 -1
- data/lib/coverband/adapters/hash_redis_store.rb +69 -15
- data/lib/coverband/adapters/null_store.rb +1 -1
- data/lib/coverband/adapters/stdout_store.rb +1 -1
- data/lib/coverband/adapters/web_service_store.rb +5 -7
- data/lib/coverband/collectors/route_tracker.rb +1 -1
- data/lib/coverband/collectors/translation_tracker.rb +2 -2
- data/lib/coverband/collectors/view_tracker.rb +1 -1
- data/lib/coverband/configuration.rb +5 -5
- data/lib/coverband/integrations/rack_server_check.rb +1 -3
- data/lib/coverband/reporters/base.rb +7 -7
- data/lib/coverband/reporters/html_report.rb +12 -4
- data/lib/coverband/reporters/json_report.rb +42 -4
- data/lib/coverband/reporters/web.rb +16 -2
- data/lib/coverband/reporters/web_pager.rb +28 -0
- data/lib/coverband/utils/absolute_file_converter.rb +19 -19
- data/lib/coverband/utils/file_hasher.rb +3 -3
- data/lib/coverband/utils/html_formatter.rb +4 -4
- data/lib/coverband/utils/method_definition_scanner.rb +1 -1
- data/lib/coverband/utils/railtie.rb +4 -6
- data/lib/coverband/utils/relative_file_converter.rb +7 -7
- data/lib/coverband/utils/results.rb +1 -5
- data/lib/coverband/utils/source_file.rb +2 -2
- data/lib/coverband/utils/tasks.rb +1 -1
- data/lib/coverband/version.rb +1 -1
- data/lib/coverband.rb +19 -3
- data/public/application.js +35 -0
- data/public/dependencies.js +1 -1
- data/roadmap.md +1 -1
- data/test/benchmarks/benchmark.rake +5 -5
- data/test/coverband/adapters/file_store_test.rb +1 -1
- data/test/coverband/collectors/coverage_test.rb +1 -1
- data/test/coverband/reporters/json_test.rb +1 -1
- data/test/coverband/utils/source_file_test.rb +11 -11
- data/test/fixtures/casting_invitor.rb +1 -1
- data/test/fixtures/sample.rb +2 -2
- data/test/fixtures/skipped_and_executed.rb +1 -1
- data/test/forked/rails_rake_full_stack_test.rb +1 -1
- data/test/test_helper.rb +3 -5
- data/test/unique_files.rb +1 -1
- data/views/file_list.erb +38 -32
- data/views/layout.erb +3 -3
- metadata +12 -136
- data/LICENSE.txt +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f25f2799e62201b31472588ed6ee3d00697b6ab8eba5beb04c3a76cb7e52d962
|
4
|
+
data.tar.gz: 599a0d1a4ef26b9b353d4ae341db2287f15b5119b9d9d3ed3d2b0e796c6e1fae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b58f4486c028a9ed4f2e3444ed164a43b620b4cc213f91e9b7aef93c2ef1c394840aade62466b216f29ade57851314989e0ed3f3bca2a7f692deddd106efe7a3
|
7
|
+
data.tar.gz: 6569ffaeb15feb24b4eb40d5e0403bcf4fcc6fc381a7fd30e64a9e6a7fee06498e05ffe2832c7a99545c51a8b25a12cf6264daf672ef82485ccf10e03a3895a3
|
data/.github/workflows/main.yml
CHANGED
@@ -20,13 +20,12 @@ jobs:
|
|
20
20
|
# truffleruby-head,
|
21
21
|
# removing jruby again to flaky
|
22
22
|
gemfile: [ Gemfile.rails6.0, Gemfile.rails6.1, Gemfile.rails7.0, Gemfile.rails7.1 ]
|
23
|
-
# ruby: [2.3, 2.4, 2.5, 2.6, 2.7, "3.0", "3.1", jruby]
|
24
23
|
# need to add support for multiple gemfiles
|
25
|
-
ruby: ["2.7", "3.0", "3.1", "3.2"]
|
24
|
+
ruby: ["2.7", "3.0", "3.1", "3.2", "3.3"]
|
26
25
|
redis-version: [4, 5, 6, 7]
|
27
26
|
runs-on: ${{ matrix.os }}-latest
|
28
27
|
steps:
|
29
|
-
- uses: actions/checkout@
|
28
|
+
- uses: actions/checkout@v4
|
30
29
|
- uses: supercharge/redis-github-action@1.2.0
|
31
30
|
with:
|
32
31
|
redis-version: ${{ matrix.redis-version }}
|
data/.standard.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -79,7 +79,7 @@ run ActionController::Dispatcher.new
|
|
79
79
|
|
80
80
|
![image](https://raw.github.com/danmayer/coverband/master/docs/coverband_web_ui.png)
|
81
81
|
|
82
|
-
>
|
82
|
+
> You can check it out locally by running the [Coverband Demo App](https://github.com/danmayer/coverband_rails_example).
|
83
83
|
|
84
84
|
- View overall coverage information
|
85
85
|
|
@@ -438,6 +438,7 @@ If you submit a change please make sure the tests and benchmarks are passing.
|
|
438
438
|
- **Coverband, [Elastic APM](https://github.com/elastic/apm-agent-ruby) and resque**
|
439
439
|
- In an environment that uses the Elastic APM ruby agent, resque jobs will fail with `Transactions may not be nested. Already inside #<ElasticAPM::Transaction>` if the `elastic-apm` gem is loaded _before_ the `coverband` gem
|
440
440
|
- Put `coverage` ahead of `elastic-apm` in your Gemfile
|
441
|
+
- **Bootsnap**, The methods used by [bootsnap do not support having coverage enabled](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/compile_cache/iseq.rb#L87), so you can either have Coverband or bootsnap, but not both.
|
441
442
|
|
442
443
|
### Debugging Redis Store
|
443
444
|
|
@@ -462,4 +463,4 @@ The Coverband logo was created by [Dave Woodall](http://davewoodall.com). Thanks
|
|
462
463
|
# License
|
463
464
|
|
464
465
|
This is a MIT License project...
|
465
|
-
See the file
|
466
|
+
See the file [LICENSE](LICENSE) for copying permission.
|
data/Rakefile
CHANGED
data/changes.md
CHANGED
@@ -135,7 +135,7 @@ __NOTE: the current RCs include below, but this might turn into coverband 6.0__
|
|
135
135
|
- added support to download coverage and view data in JSON format
|
136
136
|
- documentation about working with environment variables
|
137
137
|
- add cache wiggle to avoid Redis CPU spikes (cache stampede on Redis server)
|
138
|
-
- make the nocov
|
138
|
+
- make the nocov consistent on the data download and html view
|
139
139
|
- small performance improvements
|
140
140
|
|
141
141
|
### Coverband 4.2.3
|
data/coverband.gemspec
CHANGED
@@ -18,10 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.files = `git ls-files`.split("\n").reject { |f| f.start_with?("docs") }
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
21
|
spec.require_paths = %w[lib]
|
23
22
|
|
24
|
-
spec.required_ruby_version = ">= 2.
|
23
|
+
spec.required_ruby_version = ">= 2.7"
|
25
24
|
|
26
25
|
spec.metadata = {
|
27
26
|
"homepage_uri" => "https://github.com/danmayer/coverband",
|
@@ -40,11 +39,12 @@ Gem::Specification.new do |spec|
|
|
40
39
|
spec.add_development_dependency "minitest-fork_executor"
|
41
40
|
spec.add_development_dependency "minitest-stub-const"
|
42
41
|
spec.add_development_dependency "mocha", "~> 1.7.0"
|
42
|
+
# spec.add_development_dependency "spy"
|
43
43
|
spec.add_development_dependency "rack"
|
44
44
|
spec.add_development_dependency "rack-test"
|
45
45
|
spec.add_development_dependency "rake"
|
46
46
|
spec.add_development_dependency "resque"
|
47
|
-
spec.add_development_dependency "standard", "
|
47
|
+
spec.add_development_dependency "standard", "~> 1.34.0"
|
48
48
|
spec.add_development_dependency "standardrb"
|
49
49
|
|
50
50
|
spec.add_development_dependency "coveralls"
|
@@ -35,7 +35,7 @@ module Coverband
|
|
35
35
|
raise ABSTRACT_KEY
|
36
36
|
end
|
37
37
|
|
38
|
-
def coverage(_local_type = nil)
|
38
|
+
def coverage(_local_type = nil, opts = {})
|
39
39
|
raise ABSTRACT_KEY
|
40
40
|
end
|
41
41
|
|
@@ -51,9 +51,9 @@ module Coverband
|
|
51
51
|
raise "abstract"
|
52
52
|
end
|
53
53
|
|
54
|
-
def get_coverage_report
|
54
|
+
def get_coverage_report(options = {})
|
55
55
|
coverage_cache = {}
|
56
|
-
data = Coverband.configuration.store.split_coverage(Coverband::TYPES, coverage_cache)
|
56
|
+
data = Coverband.configuration.store.split_coverage(Coverband::TYPES, coverage_cache, options)
|
57
57
|
data.merge(Coverband::MERGED_TYPE => Coverband.configuration.store.merged_coverage(Coverband::TYPES, coverage_cache))
|
58
58
|
end
|
59
59
|
|
@@ -67,12 +67,12 @@ module Coverband
|
|
67
67
|
|
68
68
|
protected
|
69
69
|
|
70
|
-
def split_coverage(types, coverage_cache)
|
70
|
+
def split_coverage(types, coverage_cache, options = {})
|
71
71
|
types.reduce({}) do |data, type|
|
72
72
|
if type == Coverband::RUNTIME_TYPE && Coverband.configuration.simulate_oneshot_lines_coverage
|
73
73
|
data.update(type => coverage_cache[type] ||= simulated_runtime_coverage)
|
74
74
|
else
|
75
|
-
data.update(type => coverage_cache[type] ||= coverage(type))
|
75
|
+
data.update(type => coverage_cache[type] ||= coverage(type, options))
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -100,7 +100,7 @@ module Coverband
|
|
100
100
|
def expand_report(report)
|
101
101
|
expanded = {}
|
102
102
|
report_time = Time.now.to_i
|
103
|
-
updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
|
103
|
+
updated_time = (type == Coverband::EAGER_TYPE) ? nil : report_time
|
104
104
|
report.each_pair do |key, line_data|
|
105
105
|
extended_data = {
|
106
106
|
FIRST_UPDATED_KEY => report_time,
|
@@ -115,7 +115,7 @@ module Coverband
|
|
115
115
|
|
116
116
|
def merge_reports(new_report, old_report, options = {})
|
117
117
|
# transparently update from RUNTIME_TYPE = nil to RUNTIME_TYPE = :runtime
|
118
|
-
# transparent update for format
|
118
|
+
# transparent update for format coverband_3_2
|
119
119
|
old_report = coverage(nil, override_type: nil) if old_report.nil? && type == Coverband::RUNTIME_TYPE
|
120
120
|
new_report = expand_report(new_report) unless options[:skip_expansion]
|
121
121
|
keys = (new_report.keys + old_report.keys).uniq
|
@@ -145,11 +145,11 @@ module Coverband
|
|
145
145
|
# TODO: This should only be 2 cases get our dup / not dups aligned
|
146
146
|
def array_add(latest, original)
|
147
147
|
if Coverband.configuration.use_oneshot_lines_coverage
|
148
|
-
latest.map!.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
|
148
|
+
latest.map!.with_index { |v, i| ((v + original[i] >= 1) ? 1 : 0) if v && original[i] }
|
149
149
|
elsif Coverband.configuration.simulate_oneshot_lines_coverage
|
150
|
-
latest.map.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
|
150
|
+
latest.map.with_index { |v, i| ((v + original[i] >= 1) ? 1 : 0) if v && original[i] }
|
151
151
|
else
|
152
|
-
latest.map.with_index { |v, i| v && original[i] ? v + original[i] : nil }
|
152
|
+
latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
@@ -34,12 +34,10 @@ module Coverband
|
|
34
34
|
else
|
35
35
|
if lock!(local_type)
|
36
36
|
Thread.new do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
unlock!(local_type)
|
42
|
-
end
|
37
|
+
result = yield(deferred_time)
|
38
|
+
set(local_type, JSON.generate(result))
|
39
|
+
ensure
|
40
|
+
unlock!(local_type)
|
43
41
|
end
|
44
42
|
end
|
45
43
|
JSON.parse(cached_result)
|
@@ -53,12 +51,22 @@ module Coverband
|
|
53
51
|
end
|
54
52
|
end
|
55
53
|
|
54
|
+
protected
|
55
|
+
|
56
|
+
def split_coverage(types, coverage_cache, options = {})
|
57
|
+
if types.is_a?(Array)
|
58
|
+
coverage_for_types(types, options)
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
56
64
|
private
|
57
65
|
|
58
66
|
# sleep in between to avoid holding other redis commands..
|
59
67
|
# with a small random offset so runtime and eager types can be processed "at the same time"
|
60
68
|
def deferred_time
|
61
|
-
rand(
|
69
|
+
rand(2.0..3.0)
|
62
70
|
end
|
63
71
|
|
64
72
|
def del(local_type)
|
@@ -109,7 +117,7 @@ module Coverband
|
|
109
117
|
@relative_file_converter = opts[:relative_file_converter] || Utils::RelativeFileConverter
|
110
118
|
|
111
119
|
@get_coverage_cache = if opts[:get_coverage_cache]
|
112
|
-
key_prefix = [REDIS_STORAGE_FORMAT_VERSION, @redis_namespace].compact.join(".")
|
120
|
+
key_prefix = [REDIS_STORAGE_FORMAT_VERSION, @redis_namespace, "v2"].compact.join(".")
|
113
121
|
GetCoverageRedisCacheStore.new(redis, key_prefix)
|
114
122
|
else
|
115
123
|
GetCoverageNullCacheStore
|
@@ -130,6 +138,7 @@ module Coverband
|
|
130
138
|
file_keys = files_set
|
131
139
|
@redis.del(*file_keys) if file_keys.any?
|
132
140
|
@redis.del(files_key)
|
141
|
+
@redis.del(files_key(type))
|
133
142
|
@get_coverage_cache.clear!(type)
|
134
143
|
end
|
135
144
|
self.type = old_type
|
@@ -147,7 +156,7 @@ module Coverband
|
|
147
156
|
|
148
157
|
def save_report(report)
|
149
158
|
report_time = Time.now.to_i
|
150
|
-
updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
|
159
|
+
updated_time = (type == Coverband::EAGER_TYPE) ? nil : report_time
|
151
160
|
keys = []
|
152
161
|
report.each_slice(@save_report_batch_size) do |slice|
|
153
162
|
files_data = slice.map { |(file, data)|
|
@@ -173,12 +182,19 @@ module Coverband
|
|
173
182
|
@redis.sadd(files_key, keys) if keys.any?
|
174
183
|
end
|
175
184
|
|
176
|
-
|
185
|
+
# TODO: refactor this and the method below and consider removing all the cached results stuff
|
186
|
+
def coverage(local_type = nil, opts = {})
|
187
|
+
page_size = opts[:page_size] || 250
|
177
188
|
cached_results = @get_coverage_cache.fetch(local_type || type) do |sleep_time|
|
178
|
-
files_set =
|
179
|
-
|
189
|
+
files_set = if opts[:page]
|
190
|
+
files_set(local_type).each_slice(page_size).to_a[opts[:page] - 1] || {}
|
191
|
+
elsif opts[:filename]
|
192
|
+
files_set(local_type).select { |filepath| filepath == opts[:filename] } || {}
|
193
|
+
else
|
194
|
+
files_set(local_type)
|
195
|
+
end
|
180
196
|
# use batches with a sleep in between to avoid overloading redis
|
181
|
-
files_set.each_slice(
|
197
|
+
files_set.each_slice(page_size).flat_map do |key_batch|
|
182
198
|
sleep sleep_time
|
183
199
|
@redis.pipelined do |pipeline|
|
184
200
|
key_batch.each do |key|
|
@@ -193,6 +209,44 @@ module Coverband
|
|
193
209
|
end
|
194
210
|
end
|
195
211
|
|
212
|
+
# NOTE: when using paging we need to ensure we have the same set of files per page in runtime and eager
|
213
|
+
def coverage_for_types(types, opts = {})
|
214
|
+
page_size = opts[:page_size] || 250
|
215
|
+
|
216
|
+
local_type = Coverband::RUNTIME_TYPE
|
217
|
+
hash_data = {}
|
218
|
+
|
219
|
+
runtime_file_set = if opts[:page]
|
220
|
+
files_set(local_type).each_slice(page_size).to_a[opts[:page] - 1] || {}
|
221
|
+
elsif opts[:filename]
|
222
|
+
files_set(local_type).select { |filepath| filepath == opts[:filename] } || {}
|
223
|
+
else
|
224
|
+
files_set(local_type)
|
225
|
+
end
|
226
|
+
hash_data[Coverband::RUNTIME_TYPE] = runtime_file_set.each_slice(page_size).flat_map do |key_batch|
|
227
|
+
@redis.pipelined do |pipeline|
|
228
|
+
key_batch.each do |key|
|
229
|
+
pipeline.hgetall(key)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
matched_file_set = files_set(Coverband::EAGER_TYPE)
|
235
|
+
.select { |filepath| runtime_file_set.include?(filepath) } || {}
|
236
|
+
hash_data[Coverband::EAGER_TYPE] = matched_file_set.each_slice(page_size).flat_map do |key_batch|
|
237
|
+
@redis.pipelined do |pipeline|
|
238
|
+
key_batch.each do |key|
|
239
|
+
pipeline.hgetall(key)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
hash_data
|
244
|
+
end
|
245
|
+
|
246
|
+
def file_count(local_type = nil)
|
247
|
+
files_set(local_type).count { |filename| !Coverband.configuration.ignore.any? { |i| filename.match(i) } }
|
248
|
+
end
|
249
|
+
|
196
250
|
def raw_store
|
197
251
|
@redis
|
198
252
|
end
|
@@ -215,7 +269,7 @@ module Coverband
|
|
215
269
|
|
216
270
|
data = coverage_data_from_redis(data_from_redis)
|
217
271
|
hash[file] = data_from_redis.select { |meta_data_key, _value| META_DATA_KEYS.include?(meta_data_key) }.merge!("data" => data)
|
218
|
-
hash[file][LAST_UPDATED_KEY] = hash[file][LAST_UPDATED_KEY].nil? || hash[file][LAST_UPDATED_KEY] == "" ? nil : hash[file][LAST_UPDATED_KEY].to_i
|
272
|
+
hash[file][LAST_UPDATED_KEY] = (hash[file][LAST_UPDATED_KEY].nil? || hash[file][LAST_UPDATED_KEY] == "") ? nil : hash[file][LAST_UPDATED_KEY].to_i
|
219
273
|
hash[file].merge!(LAST_UPDATED_KEY => hash[file][LAST_UPDATED_KEY], FIRST_UPDATED_KEY => hash[file][FIRST_UPDATED_KEY].to_i)
|
220
274
|
end
|
221
275
|
|
@@ -223,7 +277,7 @@ module Coverband
|
|
223
277
|
max = data_from_redis[FILE_LENGTH_KEY].to_i - 1
|
224
278
|
Array.new(max + 1) do |index|
|
225
279
|
line_coverage = data_from_redis[index.to_s]
|
226
|
-
line_coverage
|
280
|
+
line_coverage&.to_i
|
227
281
|
end
|
228
282
|
end
|
229
283
|
|
@@ -42,7 +42,7 @@ module Coverband
|
|
42
42
|
|
43
43
|
###
|
44
44
|
# Fetch coverband coverage via the API
|
45
|
-
# This would allow one to
|
45
|
+
# This would allow one to explore from the service and move back to the open source
|
46
46
|
# without having to reset coverage
|
47
47
|
###
|
48
48
|
def coverage(local_type = nil, opts = {})
|
@@ -98,12 +98,10 @@ module Coverband
|
|
98
98
|
def retry_failed_reports
|
99
99
|
retries = []
|
100
100
|
@failed_coverage_reports.any? do
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
retries << report_body
|
106
|
-
end
|
101
|
+
report_body = @failed_coverage_reports.pop
|
102
|
+
send_report_body(report_body)
|
103
|
+
rescue
|
104
|
+
retries << report_body
|
107
105
|
end
|
108
106
|
retries.each do |report_body|
|
109
107
|
add_retry_message(report_body)
|
@@ -65,7 +65,7 @@ module Coverband
|
|
65
65
|
|
66
66
|
# NOTE: This event was instrumented in Aug 10th 2022, but didn't make the 7.0.4 release and should be in the next release
|
67
67
|
# https://github.com/rails/rails/pull/43755
|
68
|
-
# Automatic tracking of redirects isn't
|
68
|
+
# Automatic tracking of redirects isn't available before Rails 7.1.0 (currently tested against the 7.1.0.alpha)
|
69
69
|
# We could consider back porting or patching a solution that works on previous Rails versions
|
70
70
|
ActiveSupport::Notifications.subscribe("redirect.action_dispatch") do |name, start, finish, id, payload|
|
71
71
|
Coverband.configuration.route_tracker.track_key(payload)
|
@@ -36,7 +36,7 @@ module Coverband
|
|
36
36
|
app_translation_keys = []
|
37
37
|
app_translation_files = ::I18n.load_path.select { |f| f.match(/config\/locales/) }
|
38
38
|
app_translation_files.each do |file|
|
39
|
-
app_translation_keys += flatten_hash(YAML.load_file(file)).keys
|
39
|
+
app_translation_keys += flatten_hash(YAML.load_file(file, aliases: true)).keys
|
40
40
|
end
|
41
41
|
app_translation_keys.uniq
|
42
42
|
else
|
@@ -48,7 +48,7 @@ module Coverband
|
|
48
48
|
hash.each_with_object({}) do |(k, v), h|
|
49
49
|
if v.is_a? Hash
|
50
50
|
flatten_hash(v).map do |h_k, h_v|
|
51
|
-
h["#{k}.#{h_k}"
|
51
|
+
h[:"#{k}.#{h_k}"] = h_v
|
52
52
|
end
|
53
53
|
else
|
54
54
|
h[k] = v
|
@@ -81,7 +81,7 @@ module Coverband
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def unused_keys(used_views = nil)
|
84
|
-
recently_used_views =
|
84
|
+
recently_used_views = used_keys.keys
|
85
85
|
unused_views = all_keys - recently_used_views
|
86
86
|
# since layouts don't include format we count them used if they match with ANY formats
|
87
87
|
unused_views.reject { |view| view.match(/\/layouts\//) && recently_used_views.any? { |used_view| view.include?(used_view) } }
|
@@ -93,7 +93,7 @@ module Coverband
|
|
93
93
|
@coverband_timeout = nil
|
94
94
|
@service_dev_mode = nil
|
95
95
|
@service_test_mode = nil
|
96
|
-
@
|
96
|
+
@process_type = nil
|
97
97
|
|
98
98
|
@redis_url = nil
|
99
99
|
@redis_namespace = nil
|
@@ -154,7 +154,7 @@ module Coverband
|
|
154
154
|
def background_reporting_sleep_seconds
|
155
155
|
@background_reporting_sleep_seconds ||= if service?
|
156
156
|
# default to 10m for service
|
157
|
-
Coverband.configuration.coverband_env == "production" ? 600 : 60
|
157
|
+
(Coverband.configuration.coverband_env == "production") ? 600 : 60
|
158
158
|
elsif store.is_a?(Coverband::Adapters::HashRedisStore)
|
159
159
|
# Default to 5 minutes if using the hash redis store
|
160
160
|
300
|
@@ -180,7 +180,7 @@ module Coverband
|
|
180
180
|
def store=(store)
|
181
181
|
raise "Pass in an instance of Coverband::Adapters" unless store.is_a?(Coverband::Adapters::Base)
|
182
182
|
raise "invalid configuration: only coverband service expects an API Key" if api_key && store.class.to_s != "Coverband::Adapters::WebServiceStore"
|
183
|
-
raise "invalid configuration: coverband service shouldn't have redis url set" if ENV["COVERBAND_REDIS_URL"] && store.
|
183
|
+
raise "invalid configuration: coverband service shouldn't have redis url set" if ENV["COVERBAND_REDIS_URL"] && store.instance_of?(::Coverband::Adapters::WebServiceStore)
|
184
184
|
|
185
185
|
@store = store
|
186
186
|
end
|
@@ -262,11 +262,11 @@ module Coverband
|
|
262
262
|
end
|
263
263
|
|
264
264
|
def coverband_env
|
265
|
-
ENV["RACK_ENV"] || ENV["RAILS_ENV"] || (defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : "unknown")
|
265
|
+
ENV["RACK_ENV"] || ENV["RAILS_ENV"] || ((defined?(Rails) && Rails.respond_to?(:env)) ? Rails.env : "unknown")
|
266
266
|
end
|
267
267
|
|
268
268
|
def coverband_timeout
|
269
|
-
@coverband_timeout ||= coverband_env == "development" ? 5 : 2
|
269
|
+
@coverband_timeout ||= (coverband_env == "development") ? 5 : 2
|
270
270
|
end
|
271
271
|
|
272
272
|
def service_dev_mode
|
@@ -20,10 +20,8 @@ module Coverband
|
|
20
20
|
|
21
21
|
def rails_server?
|
22
22
|
@stack.any? do |location|
|
23
|
-
(
|
24
|
-
location.path.include?("rails/commands/commands_tasks.rb") && location.label == "server" ||
|
23
|
+
location.path.include?("rails/commands/commands_tasks.rb") && location.label == "server" ||
|
25
24
|
location.path.include?("rails/commands/server/server_command.rb") && location.label == "perform"
|
26
|
-
)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
@@ -4,15 +4,15 @@ module Coverband
|
|
4
4
|
module Reporters
|
5
5
|
###
|
6
6
|
# This is the base clase for report generation
|
7
|
-
# it helps with filtering, normalization, etc for final
|
7
|
+
# it helps with filtering, normalization, etc for final report generation
|
8
8
|
###
|
9
9
|
class Base
|
10
10
|
class << self
|
11
11
|
DATA_KEY = "data"
|
12
12
|
|
13
|
-
def report(store,
|
13
|
+
def report(store, options = {})
|
14
14
|
all_roots = Coverband.configuration.all_root_paths
|
15
|
-
|
15
|
+
get_current_scov_data_imp(store, all_roots, options)
|
16
16
|
|
17
17
|
# These are extremelhy verbose but useful during coverband development, not generally for users
|
18
18
|
# Only available by uncommenting this mode is never released
|
@@ -20,7 +20,6 @@ module Coverband
|
|
20
20
|
# # msg = "report:\n #{scov_style_report.inspect}"
|
21
21
|
# # Coverband.configuration.logger.debug msg
|
22
22
|
# end
|
23
|
-
scov_style_report
|
24
23
|
end
|
25
24
|
|
26
25
|
###
|
@@ -71,7 +70,7 @@ module Coverband
|
|
71
70
|
# > [nil,0,0,1,0,1]
|
72
71
|
def merge_arrays(first, second)
|
73
72
|
merged = []
|
74
|
-
longest = first.length > second.length ? first : second
|
73
|
+
longest = (first.length > second.length) ? first : second
|
75
74
|
|
76
75
|
longest.each_with_index do |_line, index|
|
77
76
|
merged[index] = if first[index] || second[index]
|
@@ -86,12 +85,13 @@ module Coverband
|
|
86
85
|
# why do we need to merge covered files data?
|
87
86
|
# basically because paths on machines or deployed hosts could be different, so
|
88
87
|
# two different keys could point to the same filename or `line_key`
|
88
|
+
# this happens when deployment has a dynmaic path or the path change during deployment (hot code reload)
|
89
89
|
# TODO: think we are filtering based on ignore while sending to the store
|
90
90
|
# and as we also pull it out here
|
91
91
|
###
|
92
|
-
def get_current_scov_data_imp(store, roots)
|
92
|
+
def get_current_scov_data_imp(store, roots, options = {})
|
93
93
|
scov_style_report = {}
|
94
|
-
store.get_coverage_report.each_pair do |name, data|
|
94
|
+
store.get_coverage_report(options).each_pair do |name, data|
|
95
95
|
data.each_pair do |key, line_data|
|
96
96
|
next if Coverband.configuration.ignore.any? { |i| key.match(i) }
|
97
97
|
next unless line_data
|
@@ -4,17 +4,23 @@ module Coverband
|
|
4
4
|
module Reporters
|
5
5
|
class HTMLReport < Base
|
6
6
|
attr_accessor :filtered_report_files, :open_report, :notice,
|
7
|
-
:base_path, :filename
|
7
|
+
:base_path, :filename, :page
|
8
8
|
|
9
9
|
def initialize(store, options = {})
|
10
|
-
|
10
|
+
self.page = options.fetch(:page) { nil }
|
11
11
|
self.open_report = options.fetch(:open_report) { true }
|
12
12
|
# TODO: refactor notice out to top level of web only
|
13
13
|
self.notice = options.fetch(:notice) { nil }
|
14
14
|
self.base_path = options.fetch(:base_path) { "./" }
|
15
15
|
self.filename = options.fetch(:filename) { nil }
|
16
16
|
|
17
|
-
|
17
|
+
coverband_reports = Coverband::Reporters::Base.report(store, options)
|
18
|
+
# NOTE: at the moment the optimization around paging and filenames only works for hash redis store
|
19
|
+
self.filtered_report_files = if (page || filename) && store.is_a?(Coverband::Adapters::HashRedisStore)
|
20
|
+
coverband_reports
|
21
|
+
else
|
22
|
+
self.class.fix_reports(coverband_reports)
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
def file_details
|
@@ -36,12 +42,14 @@ module Coverband
|
|
36
42
|
def report_dynamic_html
|
37
43
|
Coverband::Utils::HTMLFormatter.new(filtered_report_files,
|
38
44
|
base_path: base_path,
|
39
|
-
notice: notice
|
45
|
+
notice: notice,
|
46
|
+
page: page).format_dynamic_html!
|
40
47
|
end
|
41
48
|
|
42
49
|
def report_dynamic_data
|
43
50
|
Coverband::Utils::HTMLFormatter.new(filtered_report_files,
|
44
51
|
base_path: base_path,
|
52
|
+
page: page,
|
45
53
|
notice: notice).format_dynamic_data!
|
46
54
|
end
|
47
55
|
end
|