coverband 4.2.0 → 4.2.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +29 -9
  3. data/.travis.yml +10 -1
  4. data/Gemfile +3 -1
  5. data/Gemfile.rails4 +1 -0
  6. data/README.md +40 -15
  7. data/Rakefile +14 -3
  8. data/changes.md +47 -12
  9. data/coverband.gemspec +3 -1
  10. data/lib/coverband/adapters/base.rb +60 -36
  11. data/lib/coverband/adapters/file_store.rb +8 -8
  12. data/lib/coverband/adapters/redis_store.rb +18 -10
  13. data/lib/coverband/at_exit.rb +2 -11
  14. data/lib/coverband/collectors/coverage.rb +32 -36
  15. data/lib/coverband/collectors/delta.rb +34 -28
  16. data/lib/coverband/configuration.rb +76 -32
  17. data/lib/coverband/integrations/background.rb +8 -4
  18. data/lib/coverband/integrations/{middleware.rb → background_middleware.rb} +2 -6
  19. data/lib/coverband/integrations/bundler.rb +8 -0
  20. data/lib/coverband/integrations/report_middleware.rb +15 -0
  21. data/lib/coverband/integrations/resque.rb +3 -5
  22. data/lib/coverband/reporters/base.rb +39 -14
  23. data/lib/coverband/reporters/html_report.rb +21 -27
  24. data/lib/coverband/reporters/web.rb +13 -21
  25. data/lib/coverband/utils/file_list.rb +16 -5
  26. data/lib/coverband/utils/file_path_helper.rb +14 -3
  27. data/lib/coverband/utils/html_formatter.rb +25 -8
  28. data/lib/coverband/utils/lines_classifier.rb +5 -0
  29. data/lib/coverband/utils/railtie.rb +11 -12
  30. data/lib/coverband/utils/result.rb +1 -37
  31. data/lib/coverband/utils/results.rb +51 -0
  32. data/lib/coverband/utils/source_file.rb +31 -6
  33. data/lib/coverband/utils/tasks.rb +9 -10
  34. data/lib/coverband/version.rb +1 -1
  35. data/lib/coverband.rb +32 -21
  36. data/public/application.js +27 -0
  37. data/test/benchmarks/benchmark.rake +144 -26
  38. data/test/coverband/adapters/base_test.rb +73 -42
  39. data/test/coverband/adapters/file_store_test.rb +48 -37
  40. data/test/coverband/adapters/redis_store_test.rb +41 -10
  41. data/test/coverband/at_exit_test.rb +0 -2
  42. data/test/coverband/collectors/coverage_test.rb +57 -9
  43. data/test/coverband/collectors/delta_test.rb +36 -6
  44. data/test/coverband/configuration_test.rb +47 -7
  45. data/test/coverband/coverband_test.rb +14 -2
  46. data/test/coverband/integrations/background_middleware_test.rb +44 -0
  47. data/test/coverband/integrations/background_test.rb +1 -3
  48. data/test/coverband/integrations/report_middleware_test.rb +44 -0
  49. data/test/coverband/integrations/resque_worker_test.rb +4 -3
  50. data/test/coverband/integrations/test_resque_job.rb +3 -1
  51. data/test/coverband/reporters/base_test.rb +4 -4
  52. data/test/coverband/reporters/console_test.rb +1 -2
  53. data/test/coverband/reporters/html_test.rb +58 -19
  54. data/test/coverband/reporters/web_test.rb +0 -10
  55. data/test/coverband/utils/file_groups_test.rb +11 -5
  56. data/test/coverband/utils/file_list_test.rb +5 -5
  57. data/test/coverband/utils/html_formatter_test.rb +43 -0
  58. data/test/coverband/utils/result_test.rb +6 -47
  59. data/test/coverband/utils/results_test.rb +54 -0
  60. data/test/coverband/utils/s3_report_test.rb +2 -0
  61. data/test/coverband/utils/source_file_test.rb +50 -0
  62. data/test/dog.rb.erb +12 -0
  63. data/test/forked/rails_full_stack_test.rb +106 -0
  64. data/test/forked/rails_rake_full_stack_test.rb +40 -0
  65. data/test/integration/full_stack_test.rb +17 -15
  66. data/test/rails4_dummy/Rakefile +6 -0
  67. data/test/rails4_dummy/config/application.rb +8 -9
  68. data/test/rails4_dummy/config/coverband.rb +5 -3
  69. data/test/rails5_dummy/Rakefile +6 -0
  70. data/test/rails5_dummy/config/application.rb +6 -10
  71. data/test/rails5_dummy/config/coverband.rb +4 -2
  72. data/test/rails_test_helper.rb +22 -5
  73. data/test/test_helper.rb +42 -4
  74. data/test/unique_files.rb +17 -9
  75. data/views/file_list.erb +2 -2
  76. data/views/gem_list.erb +10 -1
  77. data/views/layout.erb +10 -3
  78. data/views/source_file.erb +13 -4
  79. data/views/source_file_loader.erb +1 -1
  80. metadata +52 -9
  81. data/test/coverband/integrations/middleware_test.rb +0 -96
  82. data/test/integration/rails_full_stack_test.rb +0 -95
@@ -9,36 +9,61 @@ module Coverband
9
9
  class Base
10
10
  class << self
11
11
  include Coverband::Utils::FilePathHelper
12
+
13
+ DATA_KEY = 'data'
14
+
12
15
  def report(store, _options = {})
13
16
  all_roots = Coverband.configuration.all_root_paths
14
17
  scov_style_report = get_current_scov_data_imp(store, all_roots)
15
18
 
16
- if Coverband.configuration.verbose
17
- msg = "report:\n #{scov_style_report.inspect}"
18
- # Coverband.configuration.logger.debug msg
19
- end
19
+ # These are extremelhy verbose but useful during coverband development, not generally for users
20
+ # if Coverband.configuration.verbose
21
+ # # msg = "report:\n #{scov_style_report.inspect}"
22
+ # # Coverband.configuration.logger.debug msg
23
+ # end
20
24
  scov_style_report
21
25
  end
22
26
 
27
+ ###
28
+ # Add back files that exist in the project but have no Coverage
29
+ # This makes it easy to find and delete files with no references
30
+ ###
31
+ def fix_reports(reports)
32
+ # list all files, even if not tracked by Coverband (0% coverage)
33
+ tracked_glob = "#{Coverband.configuration.current_root}/{app,lib,config}/**/*.{rb}"
34
+ filtered_report_files = {}
35
+
36
+ reports.each_pair do |report_name, report_data|
37
+ filtered_report_files[report_name] = {}
38
+ report_files = Coverband::Utils::Result.add_not_loaded_files(report_data, tracked_glob)
39
+
40
+ # apply coverband filters
41
+ report_files.each_pair do |file, data|
42
+ next if Coverband.configuration.ignore.any? { |i| file.match(i) }
43
+
44
+ filtered_report_files[report_name][file] = data
45
+ end
46
+ end
47
+ filtered_report_files
48
+ end
49
+
23
50
  protected
24
51
 
25
52
  def fix_file_names(report_hash, roots)
26
- if Coverband.configuration.verbose
27
- Coverband.configuration.logger.info "fixing root: #{roots.join(', ')}"
28
- end
53
+ Coverband.configuration.logger.info "fixing root: #{roots.join(', ')}" if Coverband.configuration.verbose
29
54
 
30
55
  # normalize names across servers
31
56
  report_hash.each_with_object({}) do |(name, report), fixed_report|
32
57
  fixed_report[name] = {}
33
58
  report.each_pair do |key, vals|
34
59
  filename = relative_path_to_full(key, roots)
35
- fixed_report[name][filename] = if fixed_report[name].key?(filename) && fixed_report[name][filename]['data'] && vals['data']
36
- merged_data = merge_arrays(fixed_report[name][filename]['data'], vals['data'])
37
- vals['data'] = merged_data
38
- vals
39
- else
40
- vals
41
- end
60
+ fixed_report[name][filename] = if fixed_report[name].key?(filename) && fixed_report[name][filename][DATA_KEY] && vals[DATA_KEY]
61
+ merged_data = merge_arrays(fixed_report[name][filename][DATA_KEY], vals[DATA_KEY])
62
+ vals[DATA_KEY] = merged_data
63
+ vals
64
+ else
65
+ vals
66
+ end
42
67
  end
43
68
  end
44
69
  end
@@ -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
@@ -55,7 +63,7 @@ module Coverband
55
63
  notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params['notice'])}<br/>"
56
64
  notice = request.params['notice'] ? notice : ''
57
65
  Coverband::Reporters::HTMLReport.new(Coverband.configuration.store,
58
- html: true,
66
+ static: false,
59
67
  base_path: base_path,
60
68
  notice: notice,
61
69
  open_report: false).report
@@ -77,12 +85,6 @@ module Coverband
77
85
  open_report: false).file_details
78
86
  end
79
87
 
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
88
  def clear
87
89
  if Coverband.configuration.web_enable_clear
88
90
  Coverband.configuration.store.clear!
@@ -104,16 +106,6 @@ module Coverband
104
106
  [301, { 'Location' => "#{base_path}?notice=#{notice}" }, []]
105
107
  end
106
108
 
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
109
  private
118
110
 
119
111
  # This method should get the root mounted endpoint
@@ -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
@@ -6,16 +6,25 @@
6
6
  module Coverband
7
7
  module Utils
8
8
  module FilePathHelper
9
+ module_function
10
+
11
+ @@path_cache = {}
12
+
9
13
  ###
10
14
  # Takes a full path and converts to a relative path
11
15
  ###
12
16
  def full_path_to_relative(full_path)
17
+ return @@path_cache[full_path] if @@path_cache.key?(full_path)
18
+
13
19
  relative_filename = full_path
14
- Coverband.configuration.all_root_paths.each do |root|
15
- relative_filename = relative_filename.gsub(/^#{root}/, './')
20
+ Coverband.configuration.all_root_patterns.each do |root|
21
+ relative_filename = relative_filename.sub(root, './')
16
22
  # once we have a relative path break out of the loop
17
23
  break if relative_filename.start_with? './'
18
24
  end
25
+
26
+ @@path_cache[full_path] = relative_filename
27
+
19
28
  relative_filename
20
29
  end
21
30
 
@@ -40,7 +49,9 @@ module Coverband
40
49
  relative_filename = relative_path
41
50
  local_filename = relative_filename
42
51
  roots.each do |root|
43
- relative_filename = relative_filename.gsub(/^#{root}/, './')
52
+ relative_filename = relative_filename.sub(/^#{root}/, './')
53
+ # once we have a relative path break out of the loop
54
+ break if relative_filename.start_with? './'
44
55
  end
45
56
  # the filename for our reports is expected to be a full path.
46
57
  # roots.last should be roots << current_root}/
@@ -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
 
@@ -35,8 +35,12 @@ module Coverband
35
35
 
36
36
  def format_source_file!(filename)
37
37
  source_file = @coverage_result.file_from_path_with_type(filename)
38
-
39
- formatted_source_file(@coverage_result, source_file)
38
+
39
+ if source_file
40
+ formatted_source_file(@coverage_result, source_file)
41
+ else
42
+ 'File No Longer Available'
43
+ end
40
44
  end
41
45
 
42
46
  private
@@ -70,16 +74,25 @@ module Coverband
70
74
 
71
75
  def asset_output_path
72
76
  return @asset_output_path if defined?(@asset_output_path) && @asset_output_path
77
+
73
78
  @asset_output_path = File.join(output_path)
74
79
  FileUtils.mkdir_p(@asset_output_path)
75
80
  @asset_output_path
76
81
  end
77
82
 
83
+ def served_html?
84
+ !static_html?
85
+ end
86
+
87
+ def static_html?
88
+ base_path.nil?
89
+ end
90
+
78
91
  def assets_path(name)
79
- if base_path
80
- File.join(base_path, name)
81
- else
92
+ if static_html?
82
93
  File.join(name)
94
+ else
95
+ File.join(base_path, name)
83
96
  end
84
97
  end
85
98
 
@@ -157,7 +170,11 @@ module Coverband
157
170
  end
158
171
 
159
172
  def timeago(time)
160
- "<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
173
+ if time
174
+ "<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
175
+ else
176
+ 'Not Available'
177
+ end
161
178
  end
162
179
 
163
180
  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,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Coverband.eager_loading_coverage!
4
3
  module Coverband
5
- class Railtie < Rails::Railtie
6
- initializer 'coverband.configure' do |app|
7
- app.middleware.use Coverband::Middleware
8
- end
9
-
10
- config.after_initialize do
11
- Coverband.report_coverage(true)
12
- Coverband.configuration.logger&.debug('Coverband: reported after_initialize')
4
+ module RailsEagerLoad
5
+ def eager_load!
6
+ Coverband.eager_loading_coverage!
7
+ super
8
+ ensure
9
+ Coverband.report_coverage
13
10
  Coverband.runtime_coverage!
14
11
  end
12
+ end
13
+ Rails::Engine.prepend(RailsEagerLoad)
15
14
 
16
- config.before_initialize do
17
- Coverband.configuration.logger&.debug('Coverband: set to eager_loading')
18
- Coverband.eager_loading_coverage!
15
+ class Railtie < Rails::Railtie
16
+ initializer 'coverband.configure' do |app|
17
+ app.middleware.use Coverband::BackgroundMiddleware
19
18
  end
20
19
 
21
20
  rake_tasks do
@@ -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