coverband 3.0.0 → 3.0.1

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.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -1
  3. data/.travis.yml +3 -0
  4. data/Gemfile +1 -0
  5. data/Gemfile.rails4 +7 -0
  6. data/Gemfile.rails4.lock +164 -0
  7. data/README.md +16 -14
  8. data/changes.md +17 -4
  9. data/coverband.gemspec +11 -4
  10. data/lib/coverband/adapters/base.rb +57 -8
  11. data/lib/coverband/adapters/file_store.rb +4 -22
  12. data/lib/coverband/adapters/redis_store.rb +7 -27
  13. data/lib/coverband/collectors/coverage.rb +5 -0
  14. data/lib/coverband/configuration.rb +4 -1
  15. data/lib/coverband/integrations/background.rb +25 -1
  16. data/lib/coverband/integrations/rack_server_check.rb +27 -0
  17. data/lib/coverband/reporters/simple_cov_report.rb +1 -7
  18. data/lib/coverband/reporters/web.rb +2 -20
  19. data/lib/coverband/utils/s3_report.rb +108 -0
  20. data/lib/coverband/version.rb +1 -1
  21. data/lib/coverband.rb +4 -1
  22. data/test/benchmarks/benchmark.rake +47 -1
  23. data/test/rails4_dummy/app/controllers/dummy_controller.rb +5 -0
  24. data/test/rails4_dummy/config/application.rb +15 -0
  25. data/test/rails4_dummy/config/boot.rb +3 -0
  26. data/test/rails4_dummy/config/coverband.rb +8 -0
  27. data/test/rails4_dummy/config/environment.rb +5 -0
  28. data/test/rails4_dummy/config/routes.rb +3 -0
  29. data/test/rails4_dummy/config/secrets.yml +3 -0
  30. data/test/rails4_dummy/config.ru +4 -0
  31. data/test/rails5_dummy/app/controllers/dummy_controller.rb +5 -0
  32. data/test/rails5_dummy/config/application.rb +16 -0
  33. data/test/rails5_dummy/config/coverband.rb +8 -0
  34. data/test/rails5_dummy/config/environment.rb +2 -0
  35. data/test/rails5_dummy/config/routes.rb +3 -0
  36. data/test/rails5_dummy/config.ru +3 -0
  37. data/test/rails_test_helper.rb +11 -0
  38. data/test/test_helper.rb +14 -9
  39. data/test/unit/adapters_base_test.rb +34 -13
  40. data/test/unit/adapters_file_store_test.rb +8 -4
  41. data/test/unit/adapters_redis_store_test.rb +7 -13
  42. data/test/unit/background_test.rb +16 -0
  43. data/test/unit/collectors_coverage_test.rb +24 -0
  44. data/test/unit/configuration_test.rb +12 -0
  45. data/test/unit/coverband_test.rb +26 -0
  46. data/test/unit/rack_server_checkout_test.rb +24 -0
  47. data/test/unit/rails_full_stack_test.rb +16 -0
  48. data/test/unit/reports_base_test.rb +0 -2
  49. data/test/unit/reports_console_test.rb +1 -0
  50. data/test/unit/reports_simple_cov_test.rb +1 -10
  51. data/test/unit/reports_web_test.rb +1 -3
  52. data/test/unit/utils_s3_report_test.rb +44 -0
  53. metadata +78 -9
  54. data/lib/coverband/utils/s3_report_writer.rb +0 -59
  55. data/test/unit/utils_s3_report_writer_test.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: c2b0fe96cfa4c9cfd336166b498bdbbba7d297265b5a7883d423b1b19d4738ad
4
- data.tar.gz: 31b7d38ea823730d3855fa2203da308adc862c2c8320b756c10671873f6b016e
2
+ SHA1:
3
+ metadata.gz: 6e6e4e2aa7c0271b100b0ce9dc5740719a85b6be
4
+ data.tar.gz: 4be906bc977953bcba78c7d2bcf11f288fa21d15
5
5
  SHA512:
6
- metadata.gz: 1ec633dcb00294b67974c083853cdb28148ce93fc68783aaab87fe2c343a00b880c3f5b653573cca147ce3eb2e0a1aa2933ed3629d157284fc34873838971918
7
- data.tar.gz: 5f58cce89174ca835edcbc53ce9a30a53facc276ad7ae290510380c133e640abe899087132ceff408c959fa4be5f119e8d4bb2c31b3da2b2e66b72dfae62f931
6
+ metadata.gz: f60a464c8df70d9663ae550ce40e85a3d3c72dc3e32fc27f5ea64af405b57b7354aec420b78cd83a3e60fe018cecd9b80d8f0ae26424a44b90a97f294a488345
7
+ data.tar.gz: fee9a14503b7009ac42025df790d1c70ab78a33e79eb89bf18349ec25db1213ae6730036f866e1211cb9d4f652fda29becfacf18b0bf82052bc9834328af2056
data/.gitignore CHANGED
@@ -18,4 +18,5 @@ test/tmp
18
18
  test/version_tmp
19
19
  tmp
20
20
  .byebug_history
21
- .env
21
+ .env
22
+ log/
data/.travis.yml CHANGED
@@ -3,6 +3,9 @@ rvm:
3
3
  - "2.3"
4
4
  - "2.4"
5
5
  - "2.5"
6
+ gemfile:
7
+ - Gemfile
8
+ - Gemfile.rails4
6
9
  services:
7
10
  - redis-server
8
11
  before_install:
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in coverband.gemspec
6
6
  gemspec
7
+ gem 'rails', '~>5'
data/Gemfile.rails4 ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in coverband.gemspec
6
+ gemspec
7
+ gem 'rails', '~>4'
@@ -0,0 +1,164 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ coverband (3.0.1.alpha)
5
+ simplecov (> 0.11.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionmailer (4.2.10)
11
+ actionpack (= 4.2.10)
12
+ actionview (= 4.2.10)
13
+ activejob (= 4.2.10)
14
+ mail (~> 2.5, >= 2.5.4)
15
+ rails-dom-testing (~> 1.0, >= 1.0.5)
16
+ actionpack (4.2.10)
17
+ actionview (= 4.2.10)
18
+ activesupport (= 4.2.10)
19
+ rack (~> 1.6)
20
+ rack-test (~> 0.6.2)
21
+ rails-dom-testing (~> 1.0, >= 1.0.5)
22
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
23
+ actionview (4.2.10)
24
+ activesupport (= 4.2.10)
25
+ builder (~> 3.1)
26
+ erubis (~> 2.7.0)
27
+ rails-dom-testing (~> 1.0, >= 1.0.5)
28
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
29
+ activejob (4.2.10)
30
+ activesupport (= 4.2.10)
31
+ globalid (>= 0.3.0)
32
+ activemodel (4.2.10)
33
+ activesupport (= 4.2.10)
34
+ builder (~> 3.1)
35
+ activerecord (4.2.10)
36
+ activemodel (= 4.2.10)
37
+ activesupport (= 4.2.10)
38
+ arel (~> 6.0)
39
+ activesupport (4.2.10)
40
+ i18n (~> 0.7)
41
+ minitest (~> 5.1)
42
+ thread_safe (~> 0.3, >= 0.3.4)
43
+ tzinfo (~> 1.1)
44
+ arel (6.0.4)
45
+ aws-sdk (2.11.174)
46
+ aws-sdk-resources (= 2.11.174)
47
+ aws-sdk-core (2.11.174)
48
+ aws-sigv4 (~> 1.0)
49
+ jmespath (~> 1.0)
50
+ aws-sdk-resources (2.11.174)
51
+ aws-sdk-core (= 2.11.174)
52
+ aws-sigv4 (1.0.3)
53
+ benchmark-ips (2.7.2)
54
+ builder (3.2.3)
55
+ byebug (10.0.2)
56
+ classifier-reborn (2.2.0)
57
+ fast-stemmer (~> 1.0)
58
+ coderay (1.1.2)
59
+ concurrent-ruby (1.1.3)
60
+ crass (1.0.4)
61
+ docile (1.3.1)
62
+ erubis (2.7.0)
63
+ fast-stemmer (1.0.2)
64
+ globalid (0.4.1)
65
+ activesupport (>= 4.2.0)
66
+ i18n (0.9.5)
67
+ concurrent-ruby (~> 1.0)
68
+ jmespath (1.4.0)
69
+ json (2.1.0)
70
+ loofah (2.2.3)
71
+ crass (~> 1.0.2)
72
+ nokogiri (>= 1.5.9)
73
+ m (1.5.1)
74
+ method_source (>= 0.6.7)
75
+ rake (>= 0.9.2.2)
76
+ mail (2.7.1)
77
+ mini_mime (>= 0.1.1)
78
+ memory_profiler (0.9.12)
79
+ metaclass (0.0.4)
80
+ method_source (0.9.2)
81
+ mini_mime (1.0.1)
82
+ mini_portile2 (2.3.0)
83
+ minitest (5.11.3)
84
+ mocha (0.14.0)
85
+ metaclass (~> 0.0.1)
86
+ nokogiri (1.8.5)
87
+ mini_portile2 (~> 2.3.0)
88
+ power_assert (1.1.3)
89
+ pry (0.12.2)
90
+ coderay (~> 1.1.0)
91
+ method_source (~> 0.9.0)
92
+ pry-byebug (3.6.0)
93
+ byebug (~> 10.0)
94
+ pry (~> 0.10)
95
+ rack (1.6.11)
96
+ rack-test (0.6.3)
97
+ rack (>= 1.0)
98
+ rails (4.2.10)
99
+ actionmailer (= 4.2.10)
100
+ actionpack (= 4.2.10)
101
+ actionview (= 4.2.10)
102
+ activejob (= 4.2.10)
103
+ activemodel (= 4.2.10)
104
+ activerecord (= 4.2.10)
105
+ activesupport (= 4.2.10)
106
+ bundler (>= 1.3.0, < 2.0)
107
+ railties (= 4.2.10)
108
+ sprockets-rails
109
+ rails-deprecated_sanitizer (1.0.3)
110
+ activesupport (>= 4.2.0.alpha)
111
+ rails-dom-testing (1.0.9)
112
+ activesupport (>= 4.2.0, < 5.0)
113
+ nokogiri (~> 1.6)
114
+ rails-deprecated_sanitizer (>= 1.0.1)
115
+ rails-html-sanitizer (1.0.4)
116
+ loofah (~> 2.2, >= 2.2.2)
117
+ railties (4.2.10)
118
+ actionpack (= 4.2.10)
119
+ activesupport (= 4.2.10)
120
+ rake (>= 0.8.7)
121
+ thor (>= 0.18.1, < 2.0)
122
+ rake (12.3.1)
123
+ redis (4.0.3)
124
+ simplecov (0.16.1)
125
+ docile (~> 1.1)
126
+ json (>= 1.8, < 3)
127
+ simplecov-html (~> 0.10.0)
128
+ simplecov-html (0.10.2)
129
+ sprockets (3.7.2)
130
+ concurrent-ruby (~> 1.0)
131
+ rack (> 1, < 3)
132
+ sprockets-rails (3.2.1)
133
+ actionpack (>= 4.0)
134
+ activesupport (>= 4.0)
135
+ sprockets (>= 3.0.0)
136
+ test-unit (3.2.8)
137
+ power_assert
138
+ thor (0.20.3)
139
+ thread_safe (0.3.6)
140
+ tzinfo (1.2.5)
141
+ thread_safe (~> 0.1)
142
+
143
+ PLATFORMS
144
+ ruby
145
+
146
+ DEPENDENCIES
147
+ aws-sdk (~> 2)
148
+ benchmark-ips
149
+ bundler (~> 1.3)
150
+ classifier-reborn
151
+ coverband!
152
+ m
153
+ memory_profiler
154
+ mocha (~> 0.14.0)
155
+ pry-byebug
156
+ rack
157
+ rack-test
158
+ rails (~> 4)
159
+ rake
160
+ redis
161
+ test-unit
162
+
163
+ BUNDLED WITH
164
+ 1.16.2
data/README.md CHANGED
@@ -194,8 +194,9 @@ run ActionController::Dispatcher.new
194
194
  # Verify Correct Installation
195
195
 
196
196
  * boot up your application
197
+ * run app and hit a controller (via a web request, at least one request must complete)
197
198
  * run `rake coverband:coverage` this will show app initialization coverage
198
- * run app and hit a controller (hit at least +1 time over your `config.startup_delay` setting default is 0)
199
+ * make another request, or enough that your reporting frequency will trigger
199
200
  * run `rake coverband:coverage` and you should see coverage increasing for the endpoints you hit.
200
201
 
201
202
  ## Installation Session
@@ -469,21 +470,20 @@ end
469
470
 
470
471
  # protect with http basic auth
471
472
  # curl --user foo:bar http://localhost:3000/coverage
472
- basic_constraint = lambda do |request|
473
- return true if Rails.env.development?
474
- if ActionController::HttpAuthentication::Basic.has_basic_credentials?(request)
475
- credentials = ActionController::HttpAuthentication::Basic.decode_credentials(request)
476
- email, password = credentials.split(':')
477
-
478
- email == 'foo' && password = 'bar'
479
- end
480
- end
481
-
482
473
  Rails.application.routes.draw do
483
474
  # ... lots of routes
484
- constraints basic_constraint do
485
- mount Coverband::Reporters::Web.new, at: '/coverage'
475
+
476
+ # Create a Rack wrapper around the Coverband Web Reporter to support & prompt the user for basic authentication.
477
+ AuthenticatedCoverband = Rack::Builder.new do
478
+ use Rack::Auth::Basic do |username, password|
479
+ username == 'foo' && password == 'bar'
480
+ end
481
+
482
+ run Coverband::Reporters::Web.new
486
483
  end
484
+
485
+ # Connect the wrapper app to your desired endpoint.
486
+ mount AuthenticatedCoverband, at: '/coverage'
487
487
  end
488
488
  ```
489
489
 
@@ -526,7 +526,9 @@ If you are working on adding features, PRs, or bugfixes to Coverband this sectio
526
526
 
527
527
  If you submit a change please make sure the tests and benchmarks are passing.
528
528
 
529
- * run tests: `rake`
529
+ * run tests:
530
+ * `bundle exec rake`
531
+ * `BUNDLE_GEMFILE=Gemfile.rails4 bundle exec rake` (Same tests using rails 4 instead of 5)
530
532
  * view test coverage: `open coverage/index.html`
531
533
  * run the benchmarks before and after your change to see impact
532
534
  * `rake benchmarks`
data/changes.md CHANGED
@@ -30,7 +30,7 @@ Will be the fully modern release that drops maintenance legacy support in favor
30
30
  Will be a stable and fast release that drops maintenance legacy support in favor of increased performance and maintainability.
31
31
 
32
32
  - expects to drop Tracepoint collection engine
33
- - expects to drop anything below Ruby 2.3
33
+ - drop anything below Ruby 2.3
34
34
  - release begins to simplify ease of use
35
35
  - drop collectors adapter
36
36
  - reduced configuration options
@@ -44,6 +44,9 @@ Will be a stable and fast release that drops maintenance legacy support in favor
44
44
  - add additional config / protection options on Coverage clear
45
45
  - add memory benchmarks showing memory overhead of coverband
46
46
  - add articles / podcasts like prontos readme https://github.com/prontolabs/pronto
47
+ - add meta data information first seen last recorded to the coverage report views (probably need to drop simplecov for that).
48
+ - more details in this issue: https://github.com/danmayer/coverband/issues/118
49
+ - use full stack tests to prove no memory leaks when used in Rails
47
50
 
48
51
  ### Coverband_jam_session
49
52
 
@@ -68,13 +71,23 @@ Feature Ideas:
68
71
 
69
72
  # Alpha
70
73
 
71
- ### Coverband 3.0.1
72
-
73
- * ??? ;)
74
+ ### Coverband ???
74
75
 
76
+ * Add support for Railties integration
75
77
 
76
78
  # Released
77
79
 
80
+ ### Coverband 3.0.1
81
+
82
+ * update documentation around verification steps (https://github.com/danmayer/coverband/issues/135), thanks @kbaum
83
+ * resolve coverage drift issue, https://github.com/danmayer/coverband/issues/118, thanks for MD5 hash ideas @dnasseri and @kbaum
84
+ * first version of background thread coverage reporting https://github.com/danmayer/coverband/pull/138, thanks @kbaum
85
+ * auto-detection of Rack & Rails thanks @kbaum
86
+ * improved tests allowing exceptions to raise in tests @kbaum
87
+ * add support for both aws-sdk 1.x and 2.x thanks @jared
88
+ * adds memory test ensuring no memory leaks
89
+ * full stack Rails tests for Rails 4 and 5 thanks @kbaum
90
+
78
91
  ### Coverband 3.0.0
79
92
 
80
93
  * drops Tracepoint
data/coverband.gemspec CHANGED
@@ -19,22 +19,29 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
+ # to test support for sdk 1, uncomment this line
23
+ # spec.add_development_dependency 'aws-sdk', '~> 1'
24
+ # to test sdk 2 use this one
22
25
  spec.add_development_dependency 'aws-sdk', '~> 2'
26
+ spec.add_development_dependency 'benchmark-ips'
23
27
  spec.add_development_dependency 'bundler', '~> 1.3'
24
28
  spec.add_development_dependency 'mocha', '~> 0.14.0'
25
29
  spec.add_development_dependency 'rack'
26
30
  spec.add_development_dependency 'rack-test'
27
31
  spec.add_development_dependency 'rake'
28
- spec.add_development_dependency 'test-unit'
29
32
  spec.add_development_dependency 'redis'
30
- spec.add_development_dependency 'benchmark-ips'
33
+ spec.add_development_dependency 'test-unit'
34
+ spec.add_development_dependency 'm'
35
+ spec.add_development_dependency 'memory_profiler'
36
+
31
37
  # used for benchmarking and tests
32
38
  spec.add_development_dependency 'classifier-reborn'
33
39
  # add when debugging
34
40
  # require 'byebug'; byebug
35
- spec.add_development_dependency 'byebug'
41
+ spec.add_development_dependency 'pry-byebug'
36
42
 
37
- # todo make an optional dependency for simplecov reports
43
+ # TODO: make an optional dependency for simplecov reports
38
44
  # also likely should just require simplecov-html not the whole lib
45
+ # I tried this but it was harder than I thought
39
46
  spec.add_runtime_dependency 'simplecov', '> 0.11.1'
40
47
  end
@@ -4,36 +4,70 @@ module Coverband
4
4
  module Adapters
5
5
  class Base
6
6
  def initialize
7
- raise 'abstract'
7
+ @file_hash_cache = {}
8
8
  end
9
9
 
10
10
  def clear!
11
11
  raise 'abstract'
12
12
  end
13
13
 
14
- def save_report(_report)
15
- raise 'abstract'
14
+ # Note: This could lead to slight race on redis
15
+ # where multiple processes pull the old coverage and add to it then push
16
+ # the Coverband 2 had the same issue,
17
+ # and the tradeoff has always been acceptable
18
+ def save_report(report)
19
+ data = report.dup
20
+ merge_reports(data, get_report)
21
+ save_coverage(data)
16
22
  end
17
23
 
18
24
  def coverage
19
- raise 'abstract'
25
+ simple_report(get_report)
20
26
  end
21
27
 
22
28
  def covered_files
29
+ coverage.keys || []
30
+ end
31
+
32
+ def covered_lines_for_file(file)
33
+ coverage[file] || []
34
+ end
35
+
36
+ protected
37
+
38
+ def save_coverage
23
39
  raise 'abstract'
24
40
  end
25
41
 
26
- def covered_lines_for_file(_file)
42
+ def get_report
27
43
  raise 'abstract'
28
44
  end
29
45
 
30
- protected
46
+ def file_hash(file)
47
+ @file_hash_cache[file] ||= Digest::MD5.file(file).hexdigest
48
+ end
49
+
50
+ def expand_report(report)
51
+ report_time = Time.now.to_i
52
+ report.each_pair do |key, line_data|
53
+ extended_data = {
54
+ 'first_updated_at' => report_time,
55
+ 'last_updated_at' => report_time,
56
+ 'file_hash' => file_hash(key),
57
+ 'data' => line_data
58
+ }
59
+ report[key] = extended_data
60
+ end
61
+ end
31
62
 
32
63
  def merge_reports(new_report, old_report)
64
+ new_report = expand_report(new_report)
33
65
  keys = (new_report.keys + old_report.keys).uniq
34
66
  keys.each do |file|
35
- new_report[file] = if new_report[file] && old_report[file]
36
- array_add(new_report[file], old_report[file])
67
+ new_report[file] = if new_report[file] &&
68
+ old_report[file] &&
69
+ new_report[file]['file_hash'] == old_report[file]['file_hash']
70
+ merge_expanded_data(new_report[file], old_report[file])
37
71
  elsif new_report[file]
38
72
  new_report[file]
39
73
  else
@@ -43,9 +77,24 @@ module Coverband
43
77
  new_report
44
78
  end
45
79
 
80
+ def merge_expanded_data(new_expanded, old_expanded)
81
+ {
82
+ 'first_updated_at' => old_expanded['first_updated_at'],
83
+ 'last_updated_at' => new_expanded['last_updated_at'],
84
+ 'file_hash' => new_expanded['file_hash'],
85
+ 'data' => array_add(new_expanded['data'], old_expanded['data'])
86
+ }
87
+ end
88
+
46
89
  def array_add(latest, original)
47
90
  latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
48
91
  end
92
+
93
+ def simple_report(report)
94
+ report.each_with_object({}) do |(key, extended_data), simple|
95
+ simple[key] = extended_data['data']
96
+ end
97
+ end
49
98
  end
50
99
  end
51
100
  end
@@ -8,9 +8,8 @@ module Coverband
8
8
  # Not recommended for production deployment
9
9
  ###
10
10
  class FileStore < Base
11
- attr_accessor :path
12
-
13
11
  def initialize(path, _opts = {})
12
+ super()
14
13
  @path = path
15
14
 
16
15
  config_dir = File.dirname(@path)
@@ -21,32 +20,15 @@ module Coverband
21
20
  File.delete(path) if File.exist?(path)
22
21
  end
23
22
 
24
- def save_report(report)
25
- merge_reports(report, coverage)
26
- save_coverage(report)
27
- end
28
-
29
- def coverage
30
- existing_data(path)
31
- end
32
-
33
- def covered_files
34
- report = existing_data(path)
35
- existing_data(path).merge(report).keys || []
36
- end
37
-
38
- def covered_lines_for_file(file)
39
- report = existing_data(path)
40
- report[file] || []
41
- end
42
-
43
23
  private
44
24
 
25
+ attr_accessor :path
26
+
45
27
  def save_coverage(report)
46
28
  File.open(path, 'w') { |f| f.write(report.to_json) }
47
29
  end
48
30
 
49
- def existing_data(path)
31
+ def get_report
50
32
  if File.exist?(path)
51
33
  JSON.parse(File.read(path))
52
34
  else
@@ -6,9 +6,10 @@ module Coverband
6
6
  # RedisStore store a merged coverage file to redis
7
7
  ###
8
8
  class RedisStore < Base
9
- BASE_KEY = 'coverband3'
9
+ BASE_KEY = 'coverband3_1'
10
10
 
11
11
  def initialize(redis, opts = {})
12
+ super()
12
13
  @redis = redis
13
14
  @ttl = opts[:ttl]
14
15
  @redis_namespace = opts[:redis_namespace]
@@ -18,27 +19,6 @@ module Coverband
18
19
  @redis.del(base_key)
19
20
  end
20
21
 
21
- def save_report(report)
22
- # Note: This could lead to slight races
23
- # where multiple processes pull the old coverage and add to it then push
24
- # the Coverband 2 had the same issue,
25
- # and the tradeoff has always been acceptable
26
- merge_reports(report, coverage)
27
- save_coverage(base_key, report)
28
- end
29
-
30
- def coverage
31
- get_report(base_key)
32
- end
33
-
34
- def covered_files
35
- coverage.keys
36
- end
37
-
38
- def covered_lines_for_file(file)
39
- coverage[file]
40
- end
41
-
42
22
  private
43
23
 
44
24
  attr_reader :redis
@@ -47,13 +27,13 @@ module Coverband
47
27
  @base_key ||= [BASE_KEY, @redis_namespace].compact.join('.')
48
28
  end
49
29
 
50
- def save_coverage(key, data)
51
- redis.set key, data.to_json
52
- redis.expire(key, @ttl) if @ttl
30
+ def save_coverage(data)
31
+ redis.set base_key, data.to_json
32
+ redis.expire(base_key, @ttl) if @ttl
53
33
  end
54
34
 
55
- def get_report(key)
56
- data = redis.get key
35
+ def get_report
36
+ data = redis.get base_key
57
37
  data ? JSON.parse(data) : {}
58
38
  end
59
39
  end
@@ -24,12 +24,16 @@ module Coverband
24
24
  @verbose = Coverband.configuration.verbose
25
25
  @logger = Coverband.configuration.logger
26
26
  @current_thread = Thread.current
27
+ @test_env = Coverband.configuration.test_env
28
+ @background_reporting_enabled = Coverband.configuration.background_reporting_enabled
27
29
  Thread.current[:coverband_instance] = nil
28
30
  self
29
31
  end
30
32
 
31
33
  def report_coverage(force_report = false)
34
+ return Background.start if @background_reporting_enabled
32
35
  return if !ready_to_report? && !force_report
36
+
33
37
  unless @store
34
38
  @logger.debug 'no store set, no-op'
35
39
  return
@@ -44,6 +48,7 @@ module Coverband
44
48
  @logger.error "error: #{err.inspect} #{err.message}"
45
49
  @logger.error err.backtrace
46
50
  end
51
+ raise err if @test_env
47
52
  end
48
53
 
49
54
  protected
@@ -7,7 +7,8 @@ module Coverband
7
7
  :reporter, :reporting_frequency,
8
8
  :disable_on_failure_for,
9
9
  :redis_namespace, :redis_ttl,
10
- :safe_reload_files
10
+ :safe_reload_files, :background_reporting_enabled,
11
+ :background_reporting_sleep_seconds, :test_env
11
12
 
12
13
  attr_writer :logger, :s3_region, :s3_bucket, :s3_access_key_id, :s3_secret_access_key
13
14
 
@@ -29,6 +30,8 @@ module Coverband
29
30
  @s3_secret_access_key = nil
30
31
  @redis_namespace = nil
31
32
  @redis_ttl = nil
33
+ @test_env = nil
34
+ @background_reporting_sleep_seconds = 30
32
35
  end
33
36
 
34
37
  def logger
@@ -2,6 +2,30 @@
2
2
 
3
3
  module Coverband
4
4
  class Background
5
- # TODO: stub to implement background thread recording
5
+ @semaphore = Mutex.new
6
+
7
+ def self.start
8
+ return if @background_reporting_running
9
+
10
+ logger = Coverband.configuration.logger
11
+ @semaphore.synchronize do
12
+ return if @background_reporting_running
13
+
14
+ @background_reporting_running = true
15
+ sleep_seconds = Coverband.configuration.background_reporting_sleep_seconds
16
+ Thread.new do
17
+ loop do
18
+ Coverband::Collectors::Coverage.instance.report_coverage
19
+ logger&.debug("Reported coverage from thread. Sleeping for #{sleep_seconds} seconds")
20
+ sleep(sleep_seconds)
21
+ end
22
+ end
23
+
24
+ at_exit do
25
+ Coverband::Collectors::Coverage.instance.report_coverage
26
+ logger&.debug("Reported coverage before exit")
27
+ end
28
+ end
29
+ end
6
30
  end
7
31
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ class RackServerCheck
5
+ def self.running?
6
+ new(Kernel.caller_locations).running?
7
+ end
8
+
9
+ def initialize(stack)
10
+ @stack = stack
11
+ end
12
+
13
+ def running?
14
+ rack_server? || rails_server?
15
+ end
16
+
17
+ def rack_server?
18
+ @stack.any? { |line| line.path.include?('lib/rack/') }
19
+ end
20
+
21
+ def rails_server?
22
+ @stack.any? do |location|
23
+ location.path.include?('rails/commands/commands_tasks.rb') && location.label == 'server'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -38,13 +38,7 @@ module Coverband
38
38
  Coverband.configuration.logger.info "report is ready and viewable: open #{SimpleCov.coverage_dir}/index.html"
39
39
  end
40
40
 
41
- s3_writer_options = {
42
- region: Coverband.configuration.s3_region,
43
- access_key_id: Coverband.configuration.s3_access_key_id,
44
- secret_access_key: Coverband.configuration.s3_secret_access_key
45
- }
46
- Coverband::Utils::S3ReportWriter.new(Coverband.configuration.s3_bucket,
47
- s3_writer_options).persist! if Coverband.configuration.s3_bucket
41
+ Coverband::Utils::S3Report.instance.persist! if Coverband.configuration.s3_bucket
48
42
  end
49
43
  end
50
44
  end