coverband 4.2.0 → 4.2.2

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +29 -9
  3. data/.travis.yml +10 -8
  4. data/CODE_OF_CONDUCT.md +76 -0
  5. data/Gemfile +3 -1
  6. data/Gemfile.rails4 +1 -0
  7. data/README.md +72 -43
  8. data/Rakefile +14 -3
  9. data/changes.md +66 -11
  10. data/coverband.gemspec +2 -5
  11. data/lib/coverband/adapters/base.rb +64 -45
  12. data/lib/coverband/adapters/file_store.rb +15 -9
  13. data/lib/coverband/adapters/hash_redis_store.rb +182 -0
  14. data/lib/coverband/adapters/redis_store.rb +33 -11
  15. data/lib/coverband/at_exit.rb +2 -11
  16. data/lib/coverband/collectors/coverage.rb +34 -40
  17. data/lib/coverband/collectors/delta.rb +34 -28
  18. data/lib/coverband/collectors/view_tracker.rb +124 -0
  19. data/lib/coverband/configuration.rb +96 -32
  20. data/lib/coverband/integrations/background.rb +9 -4
  21. data/lib/coverband/integrations/{middleware.rb → background_middleware.rb} +2 -6
  22. data/lib/coverband/integrations/bundler.rb +8 -0
  23. data/lib/coverband/integrations/report_middleware.rb +15 -0
  24. data/lib/coverband/integrations/resque.rb +3 -5
  25. data/lib/coverband/reporters/base.rb +40 -16
  26. data/lib/coverband/reporters/console_report.rb +1 -0
  27. data/lib/coverband/reporters/html_report.rb +21 -27
  28. data/lib/coverband/reporters/web.rb +19 -21
  29. data/lib/coverband/utils/absolute_file_converter.rb +47 -0
  30. data/lib/coverband/utils/file_hasher.rb +16 -0
  31. data/lib/coverband/utils/file_list.rb +16 -5
  32. data/lib/coverband/utils/html_formatter.rb +37 -8
  33. data/lib/coverband/utils/lines_classifier.rb +5 -0
  34. data/lib/coverband/utils/railtie.rb +20 -9
  35. data/lib/coverband/utils/relative_file_converter.rb +41 -0
  36. data/lib/coverband/utils/result.rb +1 -37
  37. data/lib/coverband/utils/results.rb +51 -0
  38. data/lib/coverband/utils/s3_report.rb +2 -2
  39. data/lib/coverband/utils/source_file.rb +31 -8
  40. data/lib/coverband/utils/tasks.rb +10 -10
  41. data/lib/coverband/version.rb +5 -1
  42. data/lib/coverband.rb +39 -22
  43. data/public/application.css +6 -6
  44. data/public/application.js +27 -0
  45. data/test/benchmarks/benchmark.rake +167 -73
  46. data/test/benchmarks/init_rails.rake +10 -0
  47. data/test/coverband/adapters/base_test.rb +73 -42
  48. data/test/coverband/adapters/file_store_test.rb +48 -37
  49. data/test/coverband/adapters/hash_redis_store_test.rb +190 -0
  50. data/test/coverband/adapters/redis_store_test.rb +92 -59
  51. data/test/coverband/at_exit_test.rb +0 -2
  52. data/test/coverband/collectors/coverage_test.rb +62 -10
  53. data/test/coverband/collectors/delta_test.rb +36 -6
  54. data/test/coverband/collectors/view_tracker_test.rb +77 -0
  55. data/test/coverband/configuration_test.rb +47 -7
  56. data/test/coverband/coverband_test.rb +14 -2
  57. data/test/coverband/integrations/background_middleware_test.rb +44 -0
  58. data/test/coverband/integrations/background_test.rb +1 -3
  59. data/test/coverband/integrations/report_middleware_test.rb +44 -0
  60. data/test/coverband/integrations/resque_worker_test.rb +6 -6
  61. data/test/coverband/integrations/test_resque_job.rb +3 -1
  62. data/test/coverband/reporters/base_test.rb +2 -79
  63. data/test/coverband/reporters/console_test.rb +2 -6
  64. data/test/coverband/reporters/html_test.rb +58 -19
  65. data/test/coverband/reporters/web_test.rb +0 -10
  66. data/test/coverband/utils/absolute_file_converter_test.rb +56 -0
  67. data/test/coverband/utils/file_groups_test.rb +11 -5
  68. data/test/coverband/utils/file_hasher_test.rb +29 -0
  69. data/test/coverband/utils/file_list_test.rb +5 -5
  70. data/test/coverband/utils/html_formatter_test.rb +43 -0
  71. data/test/coverband/utils/relative_file_converter_test.rb +39 -0
  72. data/test/coverband/utils/result_test.rb +6 -47
  73. data/test/coverband/utils/results_test.rb +54 -0
  74. data/test/coverband/utils/s3_report_test.rb +2 -0
  75. data/test/coverband/utils/source_file_test.rb +50 -0
  76. data/test/dog.rb.erb +12 -0
  77. data/test/forked/rails_full_stack_test.rb +106 -0
  78. data/test/forked/rails_rake_full_stack_test.rb +48 -0
  79. data/test/integration/full_stack_test.rb +17 -16
  80. data/test/rails4_dummy/Rakefile +6 -0
  81. data/test/rails4_dummy/config/application.rb +8 -9
  82. data/test/rails4_dummy/config/coverband.rb +5 -3
  83. data/test/rails5_dummy/Rakefile +6 -0
  84. data/test/rails5_dummy/config/application.rb +6 -10
  85. data/test/rails5_dummy/config/coverband.rb +4 -2
  86. data/test/rails_test_helper.rb +22 -5
  87. data/test/test_helper.rb +45 -8
  88. data/test/unique_files.rb +17 -9
  89. data/views/file_list.erb +2 -2
  90. data/views/gem_list.erb +10 -1
  91. data/views/layout.erb +6 -18
  92. data/views/nav.erb +35 -0
  93. data/views/source_file.erb +13 -4
  94. data/views/source_file_loader.erb +1 -1
  95. data/views/view_tracker.erb +37 -0
  96. metadata +59 -25
  97. data/lib/coverband/utils/file_path_helper.rb +0 -57
  98. data/test/coverband/integrations/middleware_test.rb +0 -96
  99. data/test/integration/rails_full_stack_test.rb +0 -95
@@ -3,13 +3,13 @@
3
3
  module Coverband
4
4
  module Reporters
5
5
  class HTMLReport < Base
6
- attr_accessor :filtered_report_files, :open_report, :html, :notice,
6
+ attr_accessor :filtered_report_files, :open_report, :static, :notice,
7
7
  :base_path, :filename
8
8
 
9
9
  def initialize(store, options = {})
10
10
  coverband_reports = Coverband::Reporters::Base.report(store, options)
11
11
  self.open_report = options.fetch(:open_report) { true }
12
- self.html = options.fetch(:html) { false }
12
+ self.static = options.fetch(:static) { true }
13
13
  # TODO: refactor notice out to top level of web only
14
14
  self.notice = options.fetch(:notice) { nil }
15
15
  self.base_path = options.fetch(:base_path) { nil }
@@ -25,40 +25,34 @@ module Coverband
25
25
  end
26
26
 
27
27
  def report
28
- if html
29
- Coverband::Utils::HTMLFormatter.new(filtered_report_files,
30
- base_path: base_path,
31
- notice: notice).format_html!
28
+ if static?
29
+ report_static_site
32
30
  else
33
- Coverband::Utils::HTMLFormatter.new(filtered_report_files).format!
34
- if open_report
35
- `open #{Coverband.configuration.root}/coverage/index.html`
36
- else
37
- Coverband.configuration.logger.info 'report is ready and viewable: open coverage/index.html'
38
- end
39
-
40
- Coverband::Utils::S3Report.instance.persist! if Coverband.configuration.s3_bucket
31
+ report_dynamic_html
41
32
  end
42
33
  end
43
34
 
44
35
  private
45
36
 
46
- def self.fix_reports(reports)
47
- # list all files, even if not tracked by Coverband (0% coverage)
48
- tracked_glob = "#{Coverband.configuration.current_root}/{app,lib,config}/**/*.{rb}"
49
- filtered_report_files = {}
37
+ def static?
38
+ static
39
+ end
50
40
 
51
- reports.each_pair do |report_name, report_data|
52
- filtered_report_files[report_name] = {}
53
- report_files = Coverband::Utils::Result.add_not_loaded_files(report_data, tracked_glob)
41
+ def report_static_site
42
+ Coverband::Utils::HTMLFormatter.new(filtered_report_files).format_static_html!
43
+ if open_report
44
+ `open #{Coverband.configuration.root}/coverage/index.html`
45
+ else
46
+ Coverband.configuration.logger.info 'report is ready and viewable: open coverage/index.html'
47
+ end
54
48
 
55
- # apply coverband filters
56
- report_files.each_pair do |file, data|
57
- next if Coverband.configuration.ignore.any? { |i| file.match(i) }
49
+ Coverband::Utils::S3Report.instance.persist! if Coverband.configuration.s3_bucket
50
+ end
58
51
 
59
- filtered_report_files[report_name][file] = data
60
- end
61
- end
52
+ def report_dynamic_html
53
+ Coverband::Utils::HTMLFormatter.new(filtered_report_files,
54
+ base_path: base_path,
55
+ notice: notice).format_dynamic_html!
62
56
  end
63
57
  end
64
58
  end
@@ -3,6 +3,7 @@
3
3
  begin
4
4
  require 'rack'
5
5
  rescue LoadError
6
+ puts 'error loading Coverband web reporter as Rack is not available'
6
7
  end
7
8
 
8
9
  module Coverband
@@ -17,19 +18,26 @@ module Coverband
17
18
  urls: [/.*\.css/, /.*\.js/, /.*\.gif/, /.*\.png/])
18
19
  end
19
20
 
21
+ def check_auth
22
+ return true unless Coverband.configuration.password
23
+
24
+ auth_header = request.get_header('HTTP_AUTHORIZATION')
25
+ return unless auth_header
26
+
27
+ Coverband.configuration.password == Base64.decode64(auth_header.split[1]).split(':')[1]
28
+ end
29
+
20
30
  def call(env)
21
31
  @request = Rack::Request.new(env)
22
32
 
33
+ return [401, { 'www-authenticate' => 'Basic realm=""' }, ['']] unless check_auth
34
+
23
35
  if request.post?
24
36
  case request.path_info
25
37
  when %r{\/clear_file}
26
38
  clear_file
27
39
  when %r{\/clear}
28
40
  clear
29
- when %r{\/collect_coverage}
30
- collect_coverage
31
- when %r{\/reload_files}
32
- reload_files
33
41
  else
34
42
  [404, { 'Content-Type' => 'text/html' }, ['404 error!']]
35
43
  end
@@ -39,6 +47,8 @@ module Coverband
39
47
  @static.call(env)
40
48
  when %r{\/settings}
41
49
  [200, { 'Content-Type' => 'text/html' }, [settings]]
50
+ when %r{\/view_tracker}
51
+ [200, { 'Content-Type' => 'text/html' }, [view_tracker]]
42
52
  when %r{\/debug_data}
43
53
  [200, { 'Content-Type' => 'text/json' }, [debug_data]]
44
54
  when %r{\/load_file_details}
@@ -55,7 +65,7 @@ module Coverband
55
65
  notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params['notice'])}<br/>"
56
66
  notice = request.params['notice'] ? notice : ''
57
67
  Coverband::Reporters::HTMLReport.new(Coverband.configuration.store,
58
- html: true,
68
+ static: false,
59
69
  base_path: base_path,
60
70
  notice: notice,
61
71
  open_report: false).report
@@ -65,6 +75,10 @@ module Coverband
65
75
  Coverband::Utils::HTMLFormatter.new(nil, base_path: base_path).format_settings!
66
76
  end
67
77
 
78
+ def view_tracker
79
+ Coverband::Utils::HTMLFormatter.new(nil, base_path: base_path).format_view_tracker!
80
+ end
81
+
68
82
  def debug_data
69
83
  Coverband.configuration.store.get_coverage_report.to_json
70
84
  end
@@ -77,12 +91,6 @@ module Coverband
77
91
  open_report: false).file_details
78
92
  end
79
93
 
80
- def collect_coverage
81
- Coverband.report_coverage(true)
82
- notice = 'coverband coverage collected'
83
- [301, { 'Location' => "#{base_path}?notice=#{notice}" }, []]
84
- end
85
-
86
94
  def clear
87
95
  if Coverband.configuration.web_enable_clear
88
96
  Coverband.configuration.store.clear!
@@ -104,16 +112,6 @@ module Coverband
104
112
  [301, { 'Location' => "#{base_path}?notice=#{notice}" }, []]
105
113
  end
106
114
 
107
- def reload_files
108
- Coverband.configuration&.safe_reload_files&.each do |safe_file|
109
- load safe_file
110
- end
111
- # force reload
112
- Coverband.configure
113
- notice = 'coverband files reloaded'
114
- [301, { 'Location' => "#{base_path}?notice=#{notice}" }, []]
115
- end
116
-
117
115
  private
118
116
 
119
117
  # This method should get the root mounted endpoint
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ module Utils
5
+ class AbsoluteFileConverter
6
+ def initialize(roots)
7
+ @cache = {}
8
+ @roots = roots.map { |root| "#{File.expand_path(root)}/" }
9
+ end
10
+
11
+ def self.instance
12
+ @instance ||= new(Coverband.configuration.all_root_paths)
13
+ end
14
+
15
+ def self.reset
16
+ @instance = nil
17
+ end
18
+
19
+ def self.convert(relative_path)
20
+ instance.convert(relative_path)
21
+ end
22
+
23
+ def convert(relative_path)
24
+ @cache[relative_path] ||= begin
25
+ relative_filename = relative_path
26
+ local_filename = relative_filename
27
+ @roots.each do |root|
28
+ relative_filename = relative_filename.sub(/^#{root}/, './')
29
+ # once we have a relative path break out of the loop
30
+ break if relative_filename.start_with? './'
31
+ end
32
+ # the filename for our reports is expected to be a full path.
33
+ # roots.last should be roots << current_root}/
34
+ # a fully expanded path of config.root
35
+ # filename = filename.gsub('./', roots.last)
36
+ # above only works for app files
37
+ # we need to rethink some of this logic
38
+ # gems aren't at project root and can have multiple locations
39
+ local_root = @roots.find do |root|
40
+ File.exist?(relative_filename.gsub('./', root))
41
+ end
42
+ local_root ? relative_filename.gsub('./', local_root) : local_filename
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ module Utils
5
+ class FileHasher
6
+ @cache = {}
7
+
8
+ def self.hash(file, path_converter: AbsoluteFileConverter.instance)
9
+ @cache[file] ||= begin
10
+ file = path_converter.convert(file)
11
+ Digest::MD5.file(file).hexdigest if File.exist?(file)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -13,24 +13,28 @@ module Coverband
13
13
  # Returns the count of lines that have coverage
14
14
  def covered_lines
15
15
  return 0.0 if empty?
16
+
16
17
  map { |f| f.covered_lines.count }.inject(:+)
17
18
  end
18
19
 
19
20
  # Returns the count of lines that have been missed
20
21
  def missed_lines
21
22
  return 0.0 if empty?
23
+
22
24
  map { |f| f.missed_lines.count }.inject(:+)
23
25
  end
24
26
 
25
27
  # Returns the count of lines that are not relevant for coverage
26
28
  def never_lines
27
29
  return 0.0 if empty?
30
+
28
31
  map { |f| f.never_lines.count }.inject(:+)
29
32
  end
30
33
 
31
34
  # Returns the count of skipped lines
32
35
  def skipped_lines
33
36
  return 0.0 if empty?
37
+
34
38
  map { |f| f.skipped_lines.count }.inject(:+)
35
39
  end
36
40
 
@@ -40,11 +44,6 @@ module Coverband
40
44
  map(&:covered_percent)
41
45
  end
42
46
 
43
- # Finds the least covered file and returns that file's name
44
- def least_covered_file
45
- sort_by(&:covered_percent).first.filename
46
- end
47
-
48
47
  # Returns the overall amount of relevant lines of code across all files in this list
49
48
  def lines_of_code
50
49
  covered_lines + missed_lines
@@ -54,15 +53,27 @@ module Coverband
54
53
  # @return [Float]
55
54
  def covered_percent
56
55
  return 100.0 if empty? || lines_of_code.zero?
56
+
57
57
  Float(covered_lines * 100.0 / lines_of_code)
58
58
  end
59
59
 
60
+ # Computes the coverage based upon lines covered and lines missed, formatted
61
+ # @return [Float]
62
+ def formatted_covered_percent
63
+ covered_percent.round(2)
64
+ end
65
+
60
66
  # Computes the strength (hits / line) based upon lines covered and lines missed
61
67
  # @return [Float]
62
68
  def covered_strength
63
69
  return 0.0 if empty? || lines_of_code.zero?
70
+
64
71
  Float(map { |f| f.covered_strength * f.lines_of_code }.inject(:+) / lines_of_code)
65
72
  end
73
+
74
+ def first_seen_at
75
+ map(&:first_updated_at).reject { |el| el.is_a?(String) }.min
76
+ end
66
77
  end
67
78
  end
68
79
  end
@@ -21,11 +21,11 @@ module Coverband
21
21
  @coverage_result = Coverband::Utils::Results.new(report) if report
22
22
  end
23
23
 
24
- def format!
24
+ def format_static_html!
25
25
  format(@coverage_result)
26
26
  end
27
27
 
28
- def format_html!
28
+ def format_dynamic_html!
29
29
  format_html(@coverage_result)
30
30
  end
31
31
 
@@ -33,10 +33,18 @@ module Coverband
33
33
  format_settings
34
34
  end
35
35
 
36
+ def format_view_tracker!
37
+ format_view_tracker
38
+ end
39
+
36
40
  def format_source_file!(filename)
37
41
  source_file = @coverage_result.file_from_path_with_type(filename)
38
-
39
- formatted_source_file(@coverage_result, source_file)
42
+
43
+ if source_file
44
+ formatted_source_file(@coverage_result, source_file)
45
+ else
46
+ 'File No Longer Available'
47
+ end
40
48
  end
41
49
 
42
50
  private
@@ -45,6 +53,10 @@ module Coverband
45
53
  template('settings').result(binding)
46
54
  end
47
55
 
56
+ def format_view_tracker
57
+ template('view_tracker').result(binding)
58
+ end
59
+
48
60
  def format(result)
49
61
  Dir[File.join(File.dirname(__FILE__), '../../../public/*')].each do |path|
50
62
  FileUtils.cp_r(path, asset_output_path)
@@ -70,16 +82,25 @@ module Coverband
70
82
 
71
83
  def asset_output_path
72
84
  return @asset_output_path if defined?(@asset_output_path) && @asset_output_path
85
+
73
86
  @asset_output_path = File.join(output_path)
74
87
  FileUtils.mkdir_p(@asset_output_path)
75
88
  @asset_output_path
76
89
  end
77
90
 
91
+ def served_html?
92
+ !static_html?
93
+ end
94
+
95
+ def static_html?
96
+ base_path.nil?
97
+ end
98
+
78
99
  def assets_path(name)
79
- if base_path
80
- File.join(base_path, name)
81
- else
100
+ if static_html?
82
101
  File.join(name)
102
+ else
103
+ File.join(base_path, name)
83
104
  end
84
105
  end
85
106
 
@@ -91,6 +112,10 @@ module Coverband
91
112
  button + '</form>'
92
113
  end
93
114
 
115
+ def display_nav(nav_options = {})
116
+ template('nav').result(binding)
117
+ end
118
+
94
119
  # Returns the html for the given source_file
95
120
  def formatted_source_file(result, source_file)
96
121
  template('source_file').result(binding)
@@ -157,7 +182,11 @@ module Coverband
157
182
  end
158
183
 
159
184
  def timeago(time)
160
- "<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
185
+ if time
186
+ "<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
187
+ else
188
+ 'Not Available'
189
+ end
161
190
  end
162
191
 
163
192
  def shortened_filename(source_file)
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ####
4
+ #
5
+ # NOTE: with Ruby 2.6.0 and beyond we can replace this classifier with
6
+ # ::Coverage.line_stub
7
+ # https://ruby-doc.org/stdlib-2.6.1/libdoc/coverage/rdoc/Coverage.html#method-c-line_stub
8
+ #
4
9
  # Thanks for all the help SimpleCov https://github.com/colszowka/simplecov-html
5
10
  # initial version pulled into Coverband from Simplecov 12/04/2018
6
11
  #
@@ -1,21 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Coverband.eager_loading_coverage!
4
3
  module Coverband
4
+ module RailsEagerLoad
5
+ def eager_load!
6
+ Coverband.eager_loading_coverage!
7
+ super
8
+ end
9
+ end
10
+ Rails::Engine.prepend(RailsEagerLoad)
11
+
5
12
  class Railtie < Rails::Railtie
6
13
  initializer 'coverband.configure' do |app|
7
- app.middleware.use Coverband::Middleware
8
- end
14
+ app.middleware.use Coverband::BackgroundMiddleware
9
15
 
10
- config.after_initialize do
11
- Coverband.report_coverage(true)
12
- Coverband.configuration.logger&.debug('Coverband: reported after_initialize')
13
- Coverband.runtime_coverage!
16
+ if Coverband.configuration.track_views
17
+ CoverbandViewTracker = Coverband::Collectors::ViewTracker.new
18
+ Coverband.configuration.view_tracker = CoverbandViewTracker
19
+
20
+ ActiveSupport::Notifications.subscribe(/render_partial.action_view|render_template.action_view/) do |name, start, finish, id, payload|
21
+ CoverbandViewTracker.track_views(name, start, finish, id, payload) unless name.include?('!')
22
+ end
23
+ end
14
24
  end
15
25
 
16
- config.before_initialize do
17
- Coverband.configuration.logger&.debug('Coverband: set to eager_loading')
26
+ config.after_initialize do
18
27
  Coverband.eager_loading_coverage!
28
+ Coverband.report_coverage
29
+ Coverband.runtime_coverage!
19
30
  end
20
31
 
21
32
  rake_tasks do
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ module Utils
5
+ class RelativeFileConverter
6
+ def self.instance
7
+ @instance ||= new(Coverband.configuration.all_root_paths)
8
+ end
9
+
10
+ def self.reset
11
+ @instance = nil
12
+ end
13
+
14
+ def self.convert(file)
15
+ instance.convert(file)
16
+ end
17
+
18
+ def initialize(roots)
19
+ @cache = {}
20
+ @roots = normalize(roots)
21
+ end
22
+
23
+ def convert(file)
24
+ @cache[file] ||= begin
25
+ relative_file = file
26
+ @roots.each do |root|
27
+ relative_file = file.gsub(/^#{root}/, '.')
28
+ break relative_file if relative_file.start_with?('.')
29
+ end
30
+ relative_file
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def normalize(paths)
37
+ paths.map { |root| File.expand_path(root) }
38
+ end
39
+ end
40
+ end
41
+ end
@@ -22,11 +22,8 @@ module Coverband
22
22
  alias source_files files
23
23
  # Explicitly set the Time this result has been created
24
24
  attr_writer :created_at
25
- # Explicitly set the command name that was used for this coverage result.
26
- # Defaults to Coverband.command_name
27
- attr_writer :command_name
28
25
 
29
- def_delegators :files, :covered_percent, :covered_percentages, :least_covered_file, :covered_strength, :covered_lines, :missed_lines
26
+ def_delegators :files, :covered_percent, :covered_percentages, :covered_strength, :covered_lines, :missed_lines
30
27
  def_delegator :files, :lines_of_code, :total_lines
31
28
 
32
29
  # Initialize a new Coverband::Result from given Coverage.result (a Hash of filenames each containing an array of
@@ -37,7 +34,6 @@ module Coverband
37
34
  @files = Coverband::Utils::FileList.new(@original_result.map do |filename, coverage|
38
35
  Coverband::Utils::SourceFile.new(filename, coverage) if File.file?(filename)
39
36
  end.compact.sort_by(&:short_name))
40
- filter!
41
37
  end
42
38
 
43
39
  # Returns all filenames for source files contained in this result
@@ -55,26 +51,6 @@ module Coverband
55
51
  @created_at ||= Time.now
56
52
  end
57
53
 
58
- # The command name that launched this result.
59
- # Delegated to Coverband.command_name if not set manually
60
- def command_name
61
- @command_name ||= 'Coverband'
62
- end
63
-
64
- # Returns a hash representation of this Result that can be used for marshalling it into JSON
65
- def to_hash
66
- { command_name => { 'coverage' => coverage, 'timestamp' => created_at.to_i } }
67
- end
68
-
69
- # Loads a Coverband::Result#to_hash dump
70
- def self.from_hash(hash)
71
- command_name, data = hash.first
72
- result = new(data['coverage'])
73
- result.command_name = command_name
74
- result.created_at = Time.at(data['timestamp'])
75
- result
76
- end
77
-
78
54
  # Finds files that were to be tracked but were not loaded and initializes
79
55
  # the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
80
56
  def self.add_not_loaded_files(result, tracked_files)
@@ -89,18 +65,6 @@ module Coverband
89
65
 
90
66
  result
91
67
  end
92
-
93
- private
94
-
95
- def coverage
96
- keys = original_result.keys & filenames
97
- Hash[keys.zip(original_result.values_at(*keys))]
98
- end
99
-
100
- # Applies all configured Coverband filters on this result's source files
101
- def filter!
102
- @files = files
103
- end
104
68
  end
105
69
  end
106
70
  end
@@ -20,6 +20,41 @@ module Coverband
20
20
  get_results(results_type).source_files.find { |file| file.filename == source_file.filename }
21
21
  end
22
22
 
23
+ def runtime_relevant_coverage(source_file)
24
+ return unless eager_loading_coverage && runtime_coverage
25
+
26
+ eager_file = get_eager_file(source_file)
27
+ runtime_file = get_runtime_file(source_file)
28
+
29
+ return 0.0 unless runtime_file
30
+
31
+ return runtime_file.formatted_covered_percent unless eager_file
32
+
33
+ runtime_relavant_lines = eager_file.relevant_lines - eager_file.covered_lines_count
34
+ runtime_file.runtime_relavant_calculations(runtime_relavant_lines) { |file| file.formatted_covered_percent }
35
+ end
36
+
37
+ def runtime_relavent_lines(source_file)
38
+ return 0 unless runtime_coverage
39
+
40
+ eager_file = get_eager_file(source_file)
41
+ runtime_file = get_runtime_file(source_file)
42
+
43
+ return runtime_file.covered_lines_count unless eager_file
44
+
45
+ eager_file.relevant_lines - eager_file.covered_lines_count
46
+ end
47
+
48
+ ###
49
+ # TODO: Groups still have some issues, this should be generic for groups, but right now gem_name
50
+ # is specifically called out, need to revisit all gorups code.
51
+ ###
52
+ def group_file_list_with_type(group, file_list, results_type)
53
+ return unless get_results(results_type)
54
+
55
+ get_results(results_type).groups[group].find { |gem_files| gem_files.first.gem_name == file_list.first.gem_name }
56
+ end
57
+
23
58
  def file_from_path_with_type(full_path, results_type = :merged)
24
59
  return unless get_results(results_type)
25
60
 
@@ -44,6 +79,22 @@ module Coverband
44
79
 
45
80
  private
46
81
 
82
+ def get_eager_file(source_file)
83
+ eager_loading_coverage.source_files.find { |file| file.filename == source_file.filename }
84
+ end
85
+
86
+ def get_runtime_file(source_file)
87
+ runtime_coverage.source_files.find { |file| file.filename == source_file.filename }
88
+ end
89
+
90
+ def eager_loading_coverage
91
+ get_results(Coverband::EAGER_TYPE)
92
+ end
93
+
94
+ def runtime_coverage
95
+ get_results(Coverband::RUNTIME_TYPE)
96
+ end
97
+
47
98
  ###
48
99
  # This is a first version of lazy loading the results
49
100
  # for the full advantage we need to push lazy loading to the file level
@@ -26,8 +26,8 @@ module Coverband
26
26
  begin
27
27
  require 'aws-sdk-s3'
28
28
  rescue StandardError
29
- err_msg = 'coverband requires aws-sdk in order use S3Report.'
30
- Coverband.configuration.logger.error err_msg
29
+ err_msg = 'Coverband requires aws-sdk in order use S3Report.'
30
+ Coverband.configuration.logger&.error err_msg
31
31
  return
32
32
  end
33
33
  end