coverband 4.2.7 → 5.0.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +25 -0
  3. data/.travis.yml +2 -1
  4. data/Gemfile +5 -7
  5. data/Gemfile.rails4 +0 -3
  6. data/Gemfile.rails6 +0 -3
  7. data/README.md +8 -77
  8. data/Rakefile +17 -17
  9. data/changes.md +18 -27
  10. data/config.ru +1 -1
  11. data/coverband.gemspec +29 -34
  12. data/lib/coverband.rb +55 -43
  13. data/lib/coverband/adapters/base.rb +17 -17
  14. data/lib/coverband/adapters/file_store.rb +2 -2
  15. data/lib/coverband/adapters/hash_redis_store.rb +24 -21
  16. data/lib/coverband/adapters/redis_store.rb +12 -12
  17. data/lib/coverband/at_exit.rb +1 -1
  18. data/lib/coverband/collectors/coverage.rb +15 -27
  19. data/lib/coverband/collectors/delta.rb +19 -9
  20. data/lib/coverband/collectors/view_tracker.rb +10 -10
  21. data/lib/coverband/configuration.rb +47 -83
  22. data/lib/coverband/integrations/background.rb +3 -3
  23. data/lib/coverband/integrations/rack_server_check.rb +3 -3
  24. data/lib/coverband/reporters/base.rb +10 -10
  25. data/lib/coverband/reporters/console_report.rb +1 -1
  26. data/lib/coverband/reporters/html_report.rb +10 -30
  27. data/lib/coverband/reporters/web.rb +56 -49
  28. data/lib/coverband/utils/absolute_file_converter.rb +6 -6
  29. data/lib/coverband/utils/html_formatter.rb +32 -61
  30. data/lib/coverband/utils/railtie.rb +16 -4
  31. data/lib/coverband/utils/relative_file_converter.rb +2 -2
  32. data/lib/coverband/utils/result.rb +6 -11
  33. data/lib/coverband/utils/results.rb +0 -10
  34. data/lib/coverband/utils/source_file.rb +21 -30
  35. data/lib/coverband/utils/tasks.rb +7 -11
  36. data/lib/coverband/version.rb +1 -1
  37. data/public/application.js +0 -30
  38. data/test/benchmarks/benchmark.rake +97 -92
  39. data/test/benchmarks/dog.rb +1 -1
  40. data/test/benchmarks/init_rails.rake +4 -4
  41. data/test/coverband/adapters/base_test.rb +29 -30
  42. data/test/coverband/adapters/file_store_test.rb +15 -16
  43. data/test/coverband/adapters/hash_redis_store_test.rb +57 -57
  44. data/test/coverband/adapters/redis_store_test.rb +26 -26
  45. data/test/coverband/at_exit_test.rb +2 -2
  46. data/test/coverband/collectors/coverage_test.rb +33 -47
  47. data/test/coverband/collectors/delta_test.rb +51 -23
  48. data/test/coverband/collectors/view_tracker_test.rb +35 -35
  49. data/test/coverband/configuration_test.rb +15 -41
  50. data/test/coverband/coverband_test.rb +11 -11
  51. data/test/coverband/integrations/background_middleware_test.rb +10 -10
  52. data/test/coverband/integrations/background_test.rb +3 -2
  53. data/test/coverband/integrations/rack_server_check_test.rb +7 -7
  54. data/test/coverband/integrations/report_middleware_test.rb +9 -9
  55. data/test/coverband/integrations/resque_worker_test.rb +9 -9
  56. data/test/coverband/integrations/test_resque_job.rb +1 -1
  57. data/test/coverband/reporters/base_test.rb +9 -9
  58. data/test/coverband/reporters/console_test.rb +6 -6
  59. data/test/coverband/reporters/html_test.rb +36 -48
  60. data/test/coverband/reporters/web_test.rb +16 -18
  61. data/test/coverband/utils/absolute_file_converter_test.rb +22 -22
  62. data/test/coverband/utils/file_hasher_test.rb +6 -12
  63. data/test/coverband/utils/file_list_test.rb +13 -13
  64. data/test/coverband/utils/html_formatter_test.rb +9 -23
  65. data/test/coverband/utils/lines_classifier_test.rb +29 -29
  66. data/test/coverband/utils/relative_file_converter_test.rb +13 -13
  67. data/test/coverband/utils/result_test.rb +18 -18
  68. data/test/coverband/utils/results_test.rb +17 -17
  69. data/test/coverband/utils/source_file_line_test.rb +46 -46
  70. data/test/coverband/utils/source_file_test.rb +38 -88
  71. data/test/dog.rb +1 -1
  72. data/test/fake_app/basic_rack.rb +2 -2
  73. data/test/fixtures/app/controllers/sample_controller.rb +1 -1
  74. data/test/fixtures/app/models/user.rb +1 -1
  75. data/test/fixtures/sample.rb +1 -1
  76. data/test/fixtures/utf-8.rb +0 -2
  77. data/test/forked/rails_full_stack_test.rb +24 -27
  78. data/test/forked/rails_rake_full_stack_test.rb +7 -26
  79. data/test/integration/full_stack_test.rb +11 -22
  80. data/test/jruby_check.rb +2 -3
  81. data/test/rails4_dummy/Rakefile +1 -1
  82. data/test/rails4_dummy/config.ru +1 -1
  83. data/test/rails4_dummy/config/application.rb +4 -4
  84. data/test/rails4_dummy/config/boot.rb +2 -2
  85. data/test/rails4_dummy/config/coverband.rb +1 -1
  86. data/test/rails4_dummy/config/coverband_missing_redis.rb +1 -1
  87. data/test/rails4_dummy/config/environment.rb +1 -1
  88. data/test/rails4_dummy/config/routes.rb +2 -2
  89. data/test/rails5_dummy/Rakefile +1 -1
  90. data/test/rails5_dummy/config.ru +1 -1
  91. data/test/rails5_dummy/config/application.rb +3 -3
  92. data/test/rails5_dummy/config/coverband.rb +8 -8
  93. data/test/rails5_dummy/config/coverband_missing_redis.rb +8 -8
  94. data/test/rails5_dummy/config/environment.rb +1 -1
  95. data/test/rails5_dummy/config/routes.rb +2 -2
  96. data/test/rails6_dummy/Rakefile +1 -1
  97. data/test/rails6_dummy/config.ru +1 -1
  98. data/test/rails6_dummy/config/application.rb +4 -4
  99. data/test/rails6_dummy/config/boot.rb +2 -2
  100. data/test/rails6_dummy/config/coverband.rb +1 -1
  101. data/test/rails6_dummy/config/coverband_missing_redis.rb +1 -1
  102. data/test/rails6_dummy/config/environment.rb +1 -1
  103. data/test/rails6_dummy/config/routes.rb +2 -2
  104. data/test/rails_test_helper.rb +11 -11
  105. data/test/test_helper.rb +41 -34
  106. data/test/unique_files.rb +10 -10
  107. data/views/layout.erb +2 -12
  108. metadata +6 -45
  109. data/.rubocop.yml +0 -86
  110. data/lib/coverband/integrations/bundler.rb +0 -8
  111. data/lib/coverband/utils/file_groups.rb +0 -53
  112. data/lib/coverband/utils/gem_list.rb +0 -31
  113. data/lib/coverband/utils/s3_report.rb +0 -105
  114. data/test/coverband/utils/file_groups_test.rb +0 -61
  115. data/test/coverband/utils/gem_list_test.rb +0 -48
  116. data/test/coverband/utils/s3_report_test.rb +0 -44
  117. data/views/gem_list.erb +0 -63
@@ -3,11 +3,11 @@
3
3
  module Coverband
4
4
  module Adapters
5
5
  class Base
6
- DATA_KEY = 'data'
7
- FIRST_UPDATED_KEY = 'first_updated_at'
8
- LAST_UPDATED_KEY = 'last_updated_at'
9
- FILE_HASH = 'file_hash'
10
- ABSTRACT_KEY = 'abstract'
6
+ DATA_KEY = "data"
7
+ FIRST_UPDATED_KEY = "first_updated_at"
8
+ LAST_UPDATED_KEY = "last_updated_at"
9
+ FILE_HASH = "file_hash"
10
+ ABSTRACT_KEY = "abstract"
11
11
 
12
12
  attr_accessor :type
13
13
 
@@ -40,11 +40,11 @@ module Coverband
40
40
  end
41
41
 
42
42
  def size_in_mib
43
- format('%<size>.2f', size: (size.to_f / 2**20))
43
+ format("%<size>.2f", size: (size.to_f / 2**20))
44
44
  end
45
45
 
46
46
  def save_report(_report)
47
- raise 'abstract'
47
+ raise "abstract"
48
48
  end
49
49
 
50
50
  def get_coverage_report
@@ -76,7 +76,7 @@ module Coverband
76
76
  runtime_data = coverage(Coverband::RUNTIME_TYPE)
77
77
  eager_data = coverage(Coverband::EAGER_TYPE)
78
78
  eager_data.values do |vals|
79
- vals['data'].map! { |line_coverage| line_coverage ? (0 - line_coverage) : line_coverage }
79
+ vals["data"].map! { |line_coverage| line_coverage ? (0 - line_coverage) : line_coverage }
80
80
  end
81
81
  merge_reports(runtime_data, eager_data, skip_expansion: true)
82
82
  end
@@ -117,14 +117,14 @@ module Coverband
117
117
  keys = (new_report.keys + old_report.keys).uniq
118
118
  keys.each do |file|
119
119
  new_report[file] = if new_report[file] &&
120
- old_report[file] &&
121
- new_report[file][FILE_HASH] == old_report[file][FILE_HASH]
122
- merge_expanded_data(new_report[file], old_report[file])
123
- elsif new_report[file]
124
- new_report[file]
125
- else
126
- old_report[file]
127
- end
120
+ old_report[file] &&
121
+ new_report[file][FILE_HASH] == old_report[file][FILE_HASH]
122
+ merge_expanded_data(new_report[file], old_report[file])
123
+ elsif new_report[file]
124
+ new_report[file]
125
+ else
126
+ old_report[file]
127
+ end
128
128
  end
129
129
  new_report
130
130
  end
@@ -145,7 +145,7 @@ module Coverband
145
145
  elsif Coverband.configuration.simulate_oneshot_lines_coverage
146
146
  latest.map.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
147
147
  else
148
- latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
148
+ latest.map.with_index { |v, i| v && original[i] ? v + original[i] : nil }
149
149
  end
150
150
  end
151
151
  end
@@ -5,7 +5,7 @@ module Coverband
5
5
  ###
6
6
  # FilesStore store a merged coverage file to local disk
7
7
  # Generally this is for testing and development
8
- # Not recommended for production deployment
8
+ # Not recommended for production deployment, as it doesn't handle concurrency
9
9
  ###
10
10
  class FileStore < Base
11
11
  def initialize(path, _opts = {})
@@ -39,7 +39,7 @@ module Coverband
39
39
  def save_report(report)
40
40
  data = report.dup
41
41
  data = merge_reports(data, coverage)
42
- File.open(path, 'w') { |f| f.write(data.to_json) }
42
+ File.open(path, "w") { |f| f.write(data.to_json) }
43
43
  end
44
44
 
45
45
  def raw_store
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'securerandom'
3
+ require "securerandom"
4
4
 
5
5
  module Coverband
6
6
  module Adapters
7
7
  class HashRedisStore < Base
8
- FILE_KEY = 'file'
9
- FILE_LENGTH_KEY = 'file_length'
8
+ FILE_KEY = "file"
9
+ FILE_LENGTH_KEY = "file_length"
10
10
  META_DATA_KEYS = [DATA_KEY, FIRST_UPDATED_KEY, LAST_UPDATED_KEY, FILE_HASH].freeze
11
11
  ###
12
12
  # This key isn't related to the coverband version, but to the interal format
13
13
  # used to store data to redis. It is changed only when breaking changes to our
14
14
  # redis format are required.
15
15
  ###
16
- REDIS_STORAGE_FORMAT_VERSION = 'coverband_hash_3_3'
16
+ REDIS_STORAGE_FORMAT_VERSION = "coverband_hash_3_3"
17
17
 
18
18
  JSON_PAYLOAD_EXPIRATION = 5 * 60
19
19
 
@@ -25,14 +25,17 @@ module Coverband
25
25
  @save_report_batch_size = opts[:save_report_batch_size] || 100
26
26
  @format_version = REDIS_STORAGE_FORMAT_VERSION
27
27
  @redis = redis
28
- raise 'HashRedisStore requires redis >= 2.6.0' unless supported?
28
+ raise "HashRedisStore requires redis >= 2.6.0" unless supported?
29
29
 
30
30
  @ttl = opts[:ttl]
31
31
  @relative_file_converter = opts[:relative_file_converter] || Utils::RelativeFileConverter
32
32
  end
33
33
 
34
34
  def supported?
35
- Gem::Version.new(@redis.info['redis_version']) >= Gem::Version.new('2.6.0')
35
+ Gem::Version.new(@redis.info["redis_version"]) >= Gem::Version.new("2.6.0")
36
+ rescue Redis::CannotConnectError => error
37
+ Coverband.configuration.logger.info "Redis is not available (#{error}), Coverband not configured"
38
+ Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
36
39
  end
37
40
 
38
41
  def clear!
@@ -60,7 +63,7 @@ module Coverband
60
63
  updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
61
64
  keys = []
62
65
  report.each_slice(@save_report_batch_size) do |slice|
63
- files_data = slice.map do |(file, data)|
66
+ files_data = slice.map { |(file, data)|
64
67
  relative_file = @relative_file_converter.convert(file)
65
68
  file_hash = file_hash(relative_file)
66
69
  key = key(relative_file, file_hash: file_hash)
@@ -73,11 +76,11 @@ module Coverband
73
76
  report_time: report_time,
74
77
  updated_time: updated_time
75
78
  )
76
- end
79
+ }
77
80
  next unless files_data.any?
78
81
 
79
- arguments_key = [@redis_namespace, SecureRandom.uuid].compact.join('.')
80
- @redis.set(arguments_key, { ttl: @ttl, files_data: files_data }.to_json, ex: JSON_PAYLOAD_EXPIRATION)
82
+ arguments_key = [@redis_namespace, SecureRandom.uuid].compact.join(".")
83
+ @redis.set(arguments_key, {ttl: @ttl, files_data: files_data}.to_json, ex: JSON_PAYLOAD_EXPIRATION)
81
84
  @redis.evalsha(hash_incr_script, [arguments_key])
82
85
  end
83
86
  @redis.sadd(files_key, keys) if keys.any?
@@ -85,11 +88,11 @@ module Coverband
85
88
 
86
89
  def coverage(local_type = nil)
87
90
  files_set = files_set(local_type)
88
- @redis.pipelined do
91
+ @redis.pipelined {
89
92
  files_set.map do |key|
90
93
  @redis.hgetall(key)
91
94
  end
92
- end.each_with_object({}) do |data_from_redis, hash|
95
+ }.each_with_object({}) do |data_from_redis, hash|
93
96
  add_coverage_for_file(data_from_redis, hash)
94
97
  end
95
98
  end
@@ -99,11 +102,11 @@ module Coverband
99
102
  end
100
103
 
101
104
  def size
102
- 'not available'
105
+ "not available"
103
106
  end
104
107
 
105
108
  def size_in_mib
106
- 'not available'
109
+ "not available"
107
110
  end
108
111
 
109
112
  private
@@ -115,7 +118,7 @@ module Coverband
115
118
  return unless file_hash(file) == data_from_redis[FILE_HASH]
116
119
 
117
120
  data = coverage_data_from_redis(data_from_redis)
118
- hash[file] = data_from_redis.select { |meta_data_key, _value| META_DATA_KEYS.include?(meta_data_key) }.merge!('data' => data)
121
+ hash[file] = data_from_redis.select { |meta_data_key, _value| META_DATA_KEYS.include?(meta_data_key) }.merge!("data" => data)
119
122
  hash[file][LAST_UPDATED_KEY] = hash[file][LAST_UPDATED_KEY].blank? ? nil : hash[file][LAST_UPDATED_KEY].to_i
120
123
  hash[file].merge!(LAST_UPDATED_KEY => hash[file][LAST_UPDATED_KEY], FIRST_UPDATED_KEY => hash[file][FIRST_UPDATED_KEY].to_i)
121
124
  end
@@ -129,9 +132,9 @@ module Coverband
129
132
  end
130
133
 
131
134
  def script_input(key:, file:, file_hash:, data:, report_time:, updated_time:)
132
- coverage_data = data.each_with_index.each_with_object({}) do |(coverage, index), hash|
135
+ coverage_data = data.each_with_index.each_with_object({}) { |(coverage, index), hash|
133
136
  hash[index] = coverage if coverage
134
- end
137
+ }
135
138
  meta = {
136
139
  first_updated_at: report_time,
137
140
  file: file,
@@ -153,8 +156,8 @@ module Coverband
153
156
 
154
157
  def lua_script_content
155
158
  File.read(File.join(
156
- File.dirname(__FILE__), '../../../lua/lib/persist-coverage.lua'
157
- ))
159
+ File.dirname(__FILE__), "../../../lua/lib/persist-coverage.lua"
160
+ ))
158
161
  end
159
162
 
160
163
  def values_from_redis(local_type, files)
@@ -178,12 +181,12 @@ module Coverband
178
181
  end
179
182
 
180
183
  def key(file, local_type = nil, file_hash:)
181
- [key_prefix(local_type), file, file_hash].join('.')
184
+ [key_prefix(local_type), file, file_hash].join(".")
182
185
  end
183
186
 
184
187
  def key_prefix(local_type = nil)
185
188
  local_type ||= type
186
- [@format_version, @redis_namespace, local_type].compact.join('.')
189
+ [@format_version, @redis_namespace, local_type].compact.join(".")
187
190
  end
188
191
  end
189
192
  end
@@ -11,19 +11,19 @@ module Coverband
11
11
  # used to store data to redis. It is changed only when breaking changes to our
12
12
  # redis format are required.
13
13
  ###
14
- REDIS_STORAGE_FORMAT_VERSION = 'coverband_3_2'
14
+ REDIS_STORAGE_FORMAT_VERSION = "coverband_3_2"
15
15
 
16
16
  attr_reader :redis_namespace
17
17
 
18
18
  def initialize(redis, opts = {})
19
19
  super()
20
- @redis = redis
21
- @ttl = opts[:ttl]
20
+ @redis = redis
21
+ @ttl = opts[:ttl]
22
22
  @redis_namespace = opts[:redis_namespace]
23
- @format_version = REDIS_STORAGE_FORMAT_VERSION
24
- @keys = {}
23
+ @format_version = REDIS_STORAGE_FORMAT_VERSION
24
+ @keys = {}
25
25
  Coverband::TYPES.each do |type|
26
- @keys[type] = [@format_version, @redis_namespace, type].compact.join('.')
26
+ @keys[type] = [@format_version, @redis_namespace, type].compact.join(".")
27
27
  end
28
28
  end
29
29
 
@@ -54,15 +54,15 @@ module Coverband
54
54
  ###
55
55
  def migrate!
56
56
  reset_base_key
57
- @format_version = 'coverband3_1'
57
+ @format_version = "coverband3_1"
58
58
  previous_data = coverage
59
59
  if previous_data.empty?
60
- puts 'no previous data to migrate found'
60
+ puts "no previous data to migrate found"
61
61
  exit 0
62
62
  end
63
- relative_path_report = previous_data.each_with_object({}) do |(key, vals), fixed_report|
63
+ relative_path_report = previous_data.each_with_object({}) { |(key, vals), fixed_report|
64
64
  fixed_report[Utils::RelativeFileConverter.convert(key)] = vals
65
- end
65
+ }
66
66
  clear!
67
67
  reset_base_key
68
68
  @format_version = REDIS_STORAGE_FORMAT_VERSION
@@ -78,7 +78,7 @@ module Coverband
78
78
  local_type ||= opts.key?(:override_type) ? opts[:override_type] : type
79
79
  data = redis.get type_base_key(local_type)
80
80
  data = data ? JSON.parse(data) : {}
81
- data.delete_if { |file_path, file_data| file_hash(file_path) != file_data['file_hash'] } unless opts[:skip_hash_check]
81
+ data.delete_if { |file_path, file_data| file_hash(file_path) != file_data["file_hash"] } unless opts[:skip_hash_check]
82
82
  data
83
83
  end
84
84
 
@@ -105,7 +105,7 @@ module Coverband
105
105
  end
106
106
 
107
107
  def base_key
108
- @base_key ||= [@format_version, @redis_namespace, type].compact.join('.')
108
+ @base_key ||= [@format_version, @redis_namespace, type].compact.join(".")
109
109
  end
110
110
 
111
111
  def type_base_key(local_type)
@@ -6,7 +6,7 @@ module Coverband
6
6
 
7
7
  @at_exit_registered = nil
8
8
  def self.register
9
- return if ENV['COVERBAND_DISABLE_AT_EXIT']
9
+ return if ENV["COVERBAND_DISABLE_AT_EXIT"]
10
10
  return if @at_exit_registered
11
11
 
12
12
  @semaphore.synchronize do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
4
- require_relative 'delta'
3
+ require "singleton"
4
+ require_relative "delta"
5
5
 
6
6
  module Coverband
7
7
  module Collectors
@@ -25,7 +25,6 @@ module Coverband
25
25
  @verbose = Coverband.configuration.verbose
26
26
  @logger = Coverband.configuration.logger
27
27
  @test_env = Coverband.configuration.test_env
28
- @track_gems = Coverband.configuration.track_gems
29
28
  Delta.reset
30
29
  self
31
30
  end
@@ -49,53 +48,42 @@ module Coverband
49
48
 
50
49
  def report_coverage
51
50
  @semaphore.synchronize do
52
- raise 'no Coverband store set' unless @store
51
+ raise "no Coverband store set" unless @store
53
52
 
54
53
  files_with_line_usage = filtered_files(Delta.results)
55
54
  @store.save_report(files_with_line_usage)
56
55
  end
57
- rescue StandardError => e
58
- @logger&.error 'coverage failed to store'
56
+ rescue => e
57
+ @logger&.error "coverage failed to store"
59
58
  @logger&.error "Coverband Error: #{e.inspect} #{e.message}"
60
59
  e.backtrace.each { |line| @logger&.error line } if @verbose
61
60
  raise e if @test_env
62
61
  end
63
62
 
64
- protected
65
-
66
- ###
67
- # Normally I would break this out into additional methods
68
- # and improve the readability but this is in a tight loop
69
- # on the critical performance path, and any refactoring I come up with
70
- # would slow down the performance.
71
- ###
72
- def track_file?(file)
73
- @ignore_patterns.none? do |pattern|
74
- file.match(pattern)
75
- end && (file.start_with?(@project_directory) ||
76
- (@track_gems &&
77
- Coverband.configuration.gem_paths.any? { |path| file.start_with?(path) }))
78
- end
79
-
80
63
  private
81
64
 
82
65
  def filtered_files(new_results)
83
- new_results.select! { |file, coverage| track_file?(file) && coverage.any? { |value| value&.nonzero? } }
66
+ new_results.select! { |_file, coverage| coverage.any? { |value| value&.nonzero? } }
84
67
  new_results
85
68
  end
86
69
 
87
70
  def initialize
88
71
  @semaphore = Mutex.new
89
- raise NotImplementedError, 'Coverage needs Ruby > 2.3.0' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3.0')
72
+ raise NotImplementedError, "Coverage needs Ruby > 2.3.0" if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.3.0")
90
73
 
91
- require 'coverage'
74
+ require "coverage"
75
+ if RUBY_PLATFORM == "java"
76
+ unless ::Coverage.respond_to?(:line_stub)
77
+ require "coverband/utils/jruby_ext"
78
+ end
79
+ end
92
80
  if defined?(SimpleCov) && defined?(Rails) && defined?(Rails.env) && Rails.env.test?
93
81
  puts "Coverband: detected SimpleCov in test Env, allowing it to start Coverage"
94
82
  puts "Coverband: to ensure no error logs or missing Coverage call `SimpleCov.start` prior to requiring Coverband"
95
83
  else
96
- if Coverage.ruby_version_greater_than_or_equal_to?('2.6.0')
84
+ if Coverage.ruby_version_greater_than_or_equal_to?("2.6.0")
97
85
  ::Coverage.start(oneshot_lines: Coverband.configuration.use_oneshot_lines_coverage) unless ::Coverage.running?
98
- elsif Coverage.ruby_version_greater_than_or_equal_to?('2.5.0')
86
+ elsif Coverage.ruby_version_greater_than_or_equal_to?("2.5.0")
99
87
  ::Coverage.start unless ::Coverage.running?
100
88
  else
101
89
  ::Coverage.start
@@ -39,23 +39,33 @@ module Coverband
39
39
 
40
40
  def self.reset
41
41
  @@previous_coverage = {}
42
+ @@project_directory = File.expand_path(Coverband.configuration.root)
43
+ @@ignore_patterns = Coverband.configuration.ignore
42
44
  end
43
45
 
44
46
  private
45
47
 
46
48
  def generate
47
- # TODO: if we filtered before doing this we would avoid calculating the line diff on a ton of files
48
- # This would be a fairly noticeable perf win
49
49
  current_coverage.each_with_object({}) do |(file, line_counts), new_results|
50
+ ###
51
+ # Eager filter:
52
+ # Normally I would break this out into additional methods
53
+ # and improve the readability but this is in a tight loop
54
+ # on the critical performance path, and any refactoring I come up with
55
+ # would slow down the performance.
56
+ ###
57
+ next unless @@ignore_patterns.none? { |pattern| file.match(pattern) } &&
58
+ file.start_with?(@@project_directory)
59
+
50
60
  # This handles Coverage branch support, setup by default in
51
61
  # simplecov 0.18.x
52
62
  arr_line_counts = line_counts.is_a?(Hash) ? line_counts[:lines] : line_counts
53
63
  new_results[file] = if @@previous_coverage && @@previous_coverage[file]
54
- prev_line_counts = @@previous_coverage[file].is_a?(Hash) ? @@previous_coverage[file][:lines] : @@previous_coverage[file]
55
- array_diff(arr_line_counts, prev_line_counts)
56
- else
57
- arr_line_counts
58
- end
64
+ prev_line_counts = @@previous_coverage[file].is_a?(Hash) ? @@previous_coverage[file][:lines] : @@previous_coverage[file]
65
+ array_diff(arr_line_counts, prev_line_counts)
66
+ else
67
+ arr_line_counts
68
+ end
59
69
  end
60
70
  end
61
71
 
@@ -68,9 +78,9 @@ module Coverband
68
78
  def transform_oneshot_lines_results(results)
69
79
  results.each_with_object({}) do |(file, coverage), new_results|
70
80
  @@stubs[file] ||= ::Coverage.line_stub(file)
71
- transformed_line_counts = coverage[:oneshot_lines].each_with_object(@@stubs[file].dup) do |line_number, line_counts|
81
+ transformed_line_counts = coverage[:oneshot_lines].each_with_object(@@stubs[file].dup) { |line_number, line_counts|
72
82
  line_counts[line_number - 1] = 1
73
- end
83
+ }
74
84
  new_results[file] = transformed_line_counts
75
85
  end
76
86
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
3
+ require "singleton"
4
4
 
5
5
  module Coverband
6
6
  module Collectors
@@ -14,12 +14,12 @@ module Coverband
14
14
  # TODO: test and ensure slim, haml, and other support
15
15
  ###
16
16
  class ViewTracker
17
- DEFAULT_TARGET = Dir.glob('app/views/**/*.html.erb').reject { |file| file.match(/(_mailer)/) }
17
+ DEFAULT_TARGET = Dir.glob("app/views/**/*.html.erb").reject { |file| file.match(/(_mailer)/) }
18
18
  attr_accessor :target, :logged_views, :views_to_record
19
19
  attr_reader :logger, :roots, :store, :ignore_patterns
20
20
 
21
21
  def initialize(options = {})
22
- raise NotImplementedError, 'View Tracker requires Rails 4 or greater' unless self.class.supported_version?
22
+ raise NotImplementedError, "View Tracker requires Rails 4 or greater" unless self.class.supported_version?
23
23
 
24
24
  @project_directory = File.expand_path(Coverband.configuration.root)
25
25
  @ignore_patterns = Coverband.configuration.ignore
@@ -28,7 +28,7 @@ module Coverband
28
28
  @target = options.fetch(:target) { DEFAULT_TARGET }
29
29
 
30
30
  @roots = options.fetch(:roots) { Coverband.configuration.all_root_patterns }
31
- @roots = @roots.split(',') if @roots.is_a?(String)
31
+ @roots = @roots.split(",") if @roots.is_a?(String)
32
32
  @one_time_timestamp = false
33
33
 
34
34
  @logged_views = []
@@ -65,7 +65,7 @@ module Coverband
65
65
  normalized_views = {}
66
66
  views.each_pair do |view, time|
67
67
  roots.each do |root|
68
- view = view.gsub(/#{root}/, '')
68
+ view = view.gsub(/#{root}/, "")
69
69
  end
70
70
  normalized_views[view] = time
71
71
  end
@@ -90,7 +90,7 @@ module Coverband
90
90
  if (tracking_time = redis_store.get(tracker_time_key))
91
91
  Time.at(tracking_time.to_i).iso8601
92
92
  else
93
- 'N/A'
93
+ "N/A"
94
94
  end
95
95
  end
96
96
 
@@ -115,14 +115,14 @@ module Coverband
115
115
  redis_store.hset(tracker_key, file, reported_time)
116
116
  end
117
117
  self.views_to_record = []
118
- rescue StandardError => e
118
+ rescue => e
119
119
  # we don't want to raise errors if Coverband can't reach redis.
120
120
  # This is a nice to have not a bring the system down
121
121
  logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}"
122
122
  end
123
123
 
124
124
  def self.supported_version?
125
- defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split('.').first.to_i >= 4
125
+ defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
126
126
  end
127
127
 
128
128
  protected
@@ -154,11 +154,11 @@ module Coverband
154
154
  end
155
155
 
156
156
  def tracker_key
157
- 'render_tracker_2'
157
+ "render_tracker_2"
158
158
  end
159
159
 
160
160
  def tracker_time_key
161
- 'render_tracker_time'
161
+ "render_tracker_time"
162
162
  end
163
163
  end
164
164
  end