coverband 6.0.2 → 6.0.3.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/main.yml +2 -3
- data/.standard.yml +1 -1
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +3 -2
- data/Rakefile +1 -1
- data/changes.md +1 -1
- data/coverband.gemspec +3 -3
- data/lib/coverband/adapters/base.rb +10 -10
- data/lib/coverband/adapters/file_store.rb +1 -1
- data/lib/coverband/adapters/hash_redis_store.rb +69 -15
- data/lib/coverband/adapters/null_store.rb +1 -1
- data/lib/coverband/adapters/stdout_store.rb +1 -1
- data/lib/coverband/adapters/web_service_store.rb +5 -7
- data/lib/coverband/collectors/route_tracker.rb +1 -1
- data/lib/coverband/collectors/translation_tracker.rb +2 -2
- data/lib/coverband/collectors/view_tracker.rb +1 -1
- data/lib/coverband/configuration.rb +5 -5
- data/lib/coverband/integrations/rack_server_check.rb +1 -3
- data/lib/coverband/reporters/base.rb +7 -7
- data/lib/coverband/reporters/html_report.rb +12 -4
- data/lib/coverband/reporters/json_report.rb +42 -4
- data/lib/coverband/reporters/web.rb +16 -2
- data/lib/coverband/reporters/web_pager.rb +28 -0
- data/lib/coverband/utils/absolute_file_converter.rb +19 -19
- data/lib/coverband/utils/file_hasher.rb +3 -3
- data/lib/coverband/utils/html_formatter.rb +4 -4
- data/lib/coverband/utils/method_definition_scanner.rb +1 -1
- data/lib/coverband/utils/railtie.rb +4 -6
- data/lib/coverband/utils/relative_file_converter.rb +7 -7
- data/lib/coverband/utils/results.rb +1 -5
- data/lib/coverband/utils/source_file.rb +2 -2
- data/lib/coverband/utils/tasks.rb +1 -1
- data/lib/coverband/version.rb +1 -1
- data/lib/coverband.rb +19 -3
- data/public/application.js +35 -0
- data/public/dependencies.js +1 -1
- data/roadmap.md +1 -1
- data/test/benchmarks/benchmark.rake +5 -5
- data/test/coverband/adapters/file_store_test.rb +1 -1
- data/test/coverband/collectors/coverage_test.rb +1 -1
- data/test/coverband/reporters/json_test.rb +1 -1
- data/test/coverband/utils/source_file_test.rb +11 -11
- data/test/fixtures/casting_invitor.rb +1 -1
- data/test/fixtures/sample.rb +2 -2
- data/test/fixtures/skipped_and_executed.rb +1 -1
- data/test/forked/rails_rake_full_stack_test.rb +1 -1
- data/test/test_helper.rb +3 -5
- data/test/unique_files.rb +1 -1
- data/views/file_list.erb +38 -32
- data/views/layout.erb +3 -3
- metadata +12 -136
- data/LICENSE.txt +0 -22
@@ -5,11 +5,22 @@
|
|
5
5
|
module Coverband
|
6
6
|
module Reporters
|
7
7
|
class JSONReport < Base
|
8
|
-
attr_accessor :filtered_report_files
|
8
|
+
attr_accessor :filtered_report_files, :options, :page, :as_report, :store, :filename
|
9
9
|
|
10
10
|
def initialize(store, options = {})
|
11
|
+
self.options = options
|
12
|
+
self.page = options.fetch(:page) { nil }
|
13
|
+
self.filename = options.fetch(:filename) { nil }
|
14
|
+
self.as_report = options.fetch(:as_report) { false }
|
15
|
+
self.store = store
|
16
|
+
|
11
17
|
coverband_reports = Coverband::Reporters::Base.report(store, options)
|
12
|
-
|
18
|
+
# NOTE: paged reports can't find and add in files that has never been loaded
|
19
|
+
self.filtered_report_files = if page || filename
|
20
|
+
coverband_reports
|
21
|
+
else
|
22
|
+
self.class.fix_reports(coverband_reports)
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
15
26
|
def report
|
@@ -21,10 +32,35 @@ module Coverband
|
|
21
32
|
def report_as_json
|
22
33
|
result = Coverband::Utils::Results.new(filtered_report_files)
|
23
34
|
source_files = result.source_files
|
24
|
-
|
35
|
+
|
36
|
+
data = {
|
25
37
|
**coverage_totals(source_files),
|
26
38
|
files: coverage_files(result, source_files)
|
27
|
-
}
|
39
|
+
}
|
40
|
+
|
41
|
+
if as_report
|
42
|
+
row_data = []
|
43
|
+
data[:files].each_pair do |key, data|
|
44
|
+
row_data << [
|
45
|
+
key,
|
46
|
+
data[:covered_percent].to_s,
|
47
|
+
data[:runtime_percentage].to_s,
|
48
|
+
data[:lines_of_code].to_s,
|
49
|
+
(data[:lines_covered] + data[:lines_missed]).to_s,
|
50
|
+
data[:lines_covered].to_s,
|
51
|
+
data[:lines_runtime].to_s,
|
52
|
+
data[:lines_missed].to_s,
|
53
|
+
data[:covered_strength].to_s
|
54
|
+
]
|
55
|
+
end
|
56
|
+
filesreported = store.file_count(:runtime)
|
57
|
+
data["iTotalRecords"] = filesreported
|
58
|
+
data["iTotalDisplayRecords"] = filesreported
|
59
|
+
data["aaData"] = row_data
|
60
|
+
data.delete(:files)
|
61
|
+
data = data.as_json
|
62
|
+
end
|
63
|
+
data.to_json
|
28
64
|
end
|
29
65
|
|
30
66
|
def coverage_totals(source_files)
|
@@ -41,11 +77,13 @@ module Coverband
|
|
41
77
|
# Using a hash indexed by file name for quick lookups
|
42
78
|
def coverage_files(result, source_files)
|
43
79
|
source_files.each_with_object({}) do |source_file, hash|
|
80
|
+
runtime_coverage = result.file_with_type(source_file, Coverband::RUNTIME_TYPE)&.covered_lines_count || 0
|
44
81
|
hash[source_file.short_name] = {
|
45
82
|
never_loaded: source_file.never_loaded,
|
46
83
|
runtime_percentage: result.runtime_relevant_coverage(source_file),
|
47
84
|
lines_of_code: source_file.lines.count,
|
48
85
|
lines_covered: source_file.covered_lines.count,
|
86
|
+
lines_runtime: runtime_coverage,
|
49
87
|
lines_missed: source_file.missed_lines.count,
|
50
88
|
covered_percent: source_file.covered_percent,
|
51
89
|
covered_strength: source_file.covered_strength
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "base64"
|
3
4
|
require "coverband"
|
4
5
|
|
5
6
|
begin
|
@@ -56,7 +57,7 @@ module Coverband
|
|
56
57
|
|
57
58
|
return [401, {"www-authenticate" => 'Basic realm=""'}, [""]] unless check_auth
|
58
59
|
|
59
|
-
request_path_info = request.path_info == "" ? "/" : request.path_info
|
60
|
+
request_path_info = (request.path_info == "") ? "/" : request.path_info
|
60
61
|
tracker_route = false
|
61
62
|
Coverband.configuration.trackers.each do |tracker|
|
62
63
|
if request_path_info.match(tracker.class::REPORT_ROUTE)
|
@@ -97,6 +98,8 @@ module Coverband
|
|
97
98
|
[200, coverband_headers(content_type: "text/json"), [load_file_details]]
|
98
99
|
when %r{\/json}
|
99
100
|
[200, coverband_headers(content_type: "text/json"), [json]]
|
101
|
+
when %r{\/report_json}
|
102
|
+
[200, coverband_headers(content_type: "text/json"), [report_json]]
|
100
103
|
when %r{\/$}
|
101
104
|
[200, coverband_headers, [index]]
|
102
105
|
else
|
@@ -120,6 +123,17 @@ module Coverband
|
|
120
123
|
Coverband::Reporters::JSONReport.new(Coverband.configuration.store).report
|
121
124
|
end
|
122
125
|
|
126
|
+
def report_json
|
127
|
+
report_options = {
|
128
|
+
as_report: true
|
129
|
+
}
|
130
|
+
report_options[:page] = (request.params["page"] || 1).to_i if request.params["page"]
|
131
|
+
Coverband::Reporters::JSONReport.new(
|
132
|
+
Coverband.configuration.store,
|
133
|
+
report_options
|
134
|
+
).report
|
135
|
+
end
|
136
|
+
|
123
137
|
def settings
|
124
138
|
Coverband::Utils::HTMLFormatter.new(nil, base_path: base_path).format_settings!
|
125
139
|
end
|
@@ -218,7 +232,7 @@ module Coverband
|
|
218
232
|
# %r{\/.*\/}.match?(request.path) ? request.path.match("\/.*\/")[0] : "/"
|
219
233
|
# ^^ the above is NOT valid Ruby 2.3/2.4 even though rubocop / standard think it is
|
220
234
|
def base_path
|
221
|
-
request.path =~ %r{\/.*\/} ? request.path.match("/.*/")[0] : "/"
|
235
|
+
(request.path =~ %r{\/.*\/}) ? request.path.match("/.*/")[0] : "/"
|
222
236
|
end
|
223
237
|
end
|
224
238
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
require "coverband"
|
5
|
+
|
6
|
+
begin
|
7
|
+
require "rack"
|
8
|
+
rescue LoadError
|
9
|
+
puts "error loading Coverband web reporter as Rack is not available"
|
10
|
+
end
|
11
|
+
|
12
|
+
module Coverband
|
13
|
+
module Reporters
|
14
|
+
class WebPager < Web
|
15
|
+
def index
|
16
|
+
notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params["notice"])}<br/>"
|
17
|
+
notice = request.params["notice"] ? notice : ""
|
18
|
+
# TODO: remove the call to the store render empty table
|
19
|
+
Coverband::Reporters::HTMLReport.new(Coverband.configuration.store,
|
20
|
+
page: (request.params["page"] || 1).to_i,
|
21
|
+
static: false,
|
22
|
+
base_path: base_path,
|
23
|
+
notice: notice,
|
24
|
+
open_report: false).report
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -22,25 +22,25 @@ module Coverband
|
|
22
22
|
|
23
23
|
def convert(relative_path)
|
24
24
|
@cache[relative_path] ||= begin
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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 { |root|
|
40
|
+
File.exist?(relative_filename.gsub("./", root))
|
41
|
+
}
|
42
|
+
local_root ? relative_filename.gsub("./", local_root) : local_filename
|
43
|
+
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -7,9 +7,9 @@ module Coverband
|
|
7
7
|
|
8
8
|
def self.hash_file(file, path_converter: AbsoluteFileConverter.instance)
|
9
9
|
@cache[file] ||= begin
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
file = path_converter.convert(file)
|
11
|
+
Digest::MD5.file(file).hexdigest if File.exist?(file)
|
12
|
+
end
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -13,12 +13,13 @@ require "time"
|
|
13
13
|
module Coverband
|
14
14
|
module Utils
|
15
15
|
class HTMLFormatter
|
16
|
-
attr_reader :notice, :base_path, :tracker
|
16
|
+
attr_reader :notice, :base_path, :tracker, :page
|
17
17
|
|
18
18
|
def initialize(report, options = {})
|
19
19
|
@notice = options.fetch(:notice, nil)
|
20
20
|
@base_path = options.fetch(:base_path, "./")
|
21
21
|
@tracker = options.fetch(:tracker, nil)
|
22
|
+
@page = options.fetch(:page, nil)
|
22
23
|
@coverage_result = Coverband::Utils::Results.new(report) if report
|
23
24
|
end
|
24
25
|
|
@@ -126,11 +127,10 @@ module Coverband
|
|
126
127
|
# Returns a table containing the given source files
|
127
128
|
def formatted_file_list(title, result, source_files, options = {})
|
128
129
|
title_id = title.gsub(/^[^a-zA-Z]+/, "").gsub(/[^a-zA-Z0-9\-\_]/, "")
|
129
|
-
# Silence a warning by using the following variable to assign to
|
130
|
+
# Silence a warning by using the following variable to assign to `_`:
|
130
131
|
# "warning: possibly useless use of a variable in void context"
|
131
132
|
# The variable is used by ERB via binding.
|
132
|
-
|
133
|
-
options = options
|
133
|
+
_ = title_id, options
|
134
134
|
|
135
135
|
template("file_list").result(binding)
|
136
136
|
end
|
@@ -71,7 +71,7 @@ if defined?(RubyVM::AbstractSyntaxTree)
|
|
71
71
|
def scan_node(node, class_name)
|
72
72
|
definitions = []
|
73
73
|
return definitions unless node.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
74
|
-
current_class = node.type == :CLASS ? node.children.first.children.last : class_name
|
74
|
+
current_class = (node.type == :CLASS) ? node.children.first.children.last : class_name
|
75
75
|
if node.type == :DEFN
|
76
76
|
definitions <<
|
77
77
|
MethodDefinition.new(
|
@@ -11,12 +11,10 @@ module Coverband
|
|
11
11
|
|
12
12
|
class Railtie < Rails::Railtie
|
13
13
|
initializer "coverband.configure" do |app|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
|
19
|
-
end
|
14
|
+
app.middleware.use Coverband::BackgroundMiddleware
|
15
|
+
rescue Redis::CannotConnectError => error
|
16
|
+
Coverband.configuration.logger.info "Redis is not available (#{error}), Coverband not configured"
|
17
|
+
Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
|
20
18
|
end
|
21
19
|
|
22
20
|
config.after_initialize do
|
@@ -22,13 +22,13 @@ module Coverband
|
|
22
22
|
|
23
23
|
def convert(file)
|
24
24
|
@cache[file] ||= begin
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
32
|
end
|
33
33
|
|
34
34
|
private
|
@@ -74,7 +74,7 @@ module Coverband
|
|
74
74
|
return "skipped" if skipped?
|
75
75
|
return "never" if never?
|
76
76
|
return "missed" if missed?
|
77
|
-
|
77
|
+
"covered" if covered?
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -162,7 +162,7 @@ module Coverband
|
|
162
162
|
return 0.0 if relevant_lines.zero?
|
163
163
|
|
164
164
|
# handle edge case where runtime in dev can go over 100%
|
165
|
-
[Float(covered_lines.size * 100.0 / relevant_lines.to_f), 100.0].min
|
165
|
+
[Float(covered_lines.size * 100.0 / relevant_lines.to_f), 100.0].min&.round(2)
|
166
166
|
end
|
167
167
|
|
168
168
|
def formatted_covered_percent
|
@@ -35,7 +35,7 @@ namespace :coverband do
|
|
35
35
|
Coverband.configuration.store.merge_mode = true
|
36
36
|
end
|
37
37
|
Rack::Server.start app: Coverband::Reporters::Web.new,
|
38
|
-
|
38
|
+
Port: ENV.fetch("COVERBAND_COVERAGE_PORT", 9022).to_i
|
39
39
|
end
|
40
40
|
|
41
41
|
###
|
data/lib/coverband/version.rb
CHANGED
data/lib/coverband.rb
CHANGED
@@ -82,9 +82,9 @@ module Coverband
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.tasks_to_ignore?
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
defined?(Rake) &&
|
86
|
+
Rake.respond_to?(:application) &&
|
87
|
+
(Rake&.application&.top_level_tasks || []).any? { |task| Coverband::Configuration::IGNORE_TASKS.include?(task) }
|
88
88
|
end
|
89
89
|
|
90
90
|
def self.eager_loading_coverage!
|
@@ -130,6 +130,7 @@ module Coverband
|
|
130
130
|
###
|
131
131
|
def initialize
|
132
132
|
require "coverband/reporters/web"
|
133
|
+
require "coverband/reporters/web_pager"
|
133
134
|
require "coverband/utils/html_formatter"
|
134
135
|
require "coverband/utils/result"
|
135
136
|
require "coverband/utils/file_list"
|
@@ -147,4 +148,19 @@ module Coverband
|
|
147
148
|
end
|
148
149
|
end
|
149
150
|
end
|
151
|
+
|
152
|
+
module Reporters
|
153
|
+
class WebPager < Web
|
154
|
+
def initialize
|
155
|
+
require "coverband/reporters/web"
|
156
|
+
require "coverband/reporters/web_pager"
|
157
|
+
super
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.call(env)
|
161
|
+
@app ||= new
|
162
|
+
@app.call(env)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
150
166
|
end
|
data/public/application.js
CHANGED
@@ -33,6 +33,41 @@ $(document).ready(function() {
|
|
33
33
|
]
|
34
34
|
});
|
35
35
|
|
36
|
+
// TODO: add support for searching...
|
37
|
+
// hmm should I just use manual paging? or load more...
|
38
|
+
if ($(".file_list.unsorted").length == 1) {
|
39
|
+
var current_rows = 0;
|
40
|
+
var total_rows = 0;
|
41
|
+
var page = 1;
|
42
|
+
|
43
|
+
// write a function to get a page of data and add it to the table
|
44
|
+
function get_page(page) {
|
45
|
+
$.ajax({
|
46
|
+
url: `/coverage/report_json?page=${page}`,
|
47
|
+
type: 'GET',
|
48
|
+
dataType: 'json',
|
49
|
+
success: function(data) {
|
50
|
+
console.log(data);
|
51
|
+
total_rows = data["iTotalRecords"];
|
52
|
+
// NOTE: we request 250 at a time, but we seem to have some files that we have as a list but 0 coverage,
|
53
|
+
// so we don't get back 250 per page... to ensure we we need to account for filtered out and empty files
|
54
|
+
// this 250 at the moment is synced to the 250 in the hash redis store
|
55
|
+
current_rows += 250; //data["aaData"].length;
|
56
|
+
console.log(current_rows);
|
57
|
+
console.log(total_rows);
|
58
|
+
$(".file_list.unsorted").dataTable().fnAddData(data["aaData"]);
|
59
|
+
page += 1;
|
60
|
+
// the page less than 100 is to stop infinite loop in case of folks never clearing out old coverage reports
|
61
|
+
if (page < 100 && current_rows < total_rows) {
|
62
|
+
get_page(page);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
});
|
66
|
+
}
|
67
|
+
get_page(page);
|
68
|
+
}
|
69
|
+
|
70
|
+
|
36
71
|
// Syntax highlight all files up front - deactivated
|
37
72
|
// $('.source_table pre code').each(function(i, e) {hljs.highlightBlock(e, ' ')});
|
38
73
|
|
data/public/dependencies.js
CHANGED
@@ -1147,7 +1147,7 @@ this._iRecordsTotal:this.aiDisplayMaster.length};this.fnRecordsDisplay=function(
|
|
1147
1147
|
bSort:true,bInfo:true,bAutoWidth:true,bProcessing:false,bSortClasses:true,bStateSave:false,bServerSide:false};this.oScroll={sX:"",sXInner:"",sY:"",bCollapse:false,iBarWidth:0};this.aanFeatures=[];this.oLanguage={sProcessing:"Processing...",sLengthMenu:"Show _MENU_ entries",sZeroRecords:"No matching records found",sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",
|
1148
1148
|
sInfoPostFix:"",sSearch:"Search:",sUrl:"",oPaginate:{sFirst:"First",sPrevious:"Previous",sNext:"Next",sLast:"Last"}};this.aoData=[];this.aiDisplay=[];this.aiDisplayMaster=[];this.aoColumns=[];this.iNextId=0;this.asDataSearch=[];this.oPreviousSearch={sSearch:"",bRegex:false,bSmart:true};this.aoPreSearchCols=[];this.aaSorting=[[0,"asc",0]];this.aaSortingFixed=null;this.asStripClasses=[];this.asDestoryStrips=[];this.fnFooterCallback=this.fnHeaderCallback=this.fnRowCallback=null;this.aoDrawCallback=[];
|
1149
1149
|
this.fnInitComplete=null;this.sTableId="";this.nTableWrapper=this.nTBody=this.nTFoot=this.nTHead=this.nTable=null;this.iDefaultSortIndex=0;this.bInitialised=false;this.aoOpenRows=[];this.sDom="lfrtip";this.sPaginationType="two_button";this.iCookieDuration=7200;this.sCookiePrefix="SpryMedia_DataTables_";this.sAjaxSource=null;this.bAjaxDataGet=true;this.fnServerData=function(a,b,c){j.ajax({url:a,data:b,success:c,dataType:"json",cache:false,error:function(){alert("DataTables warning: JSON data from server failed to load or be parsed. This is most likely to be caused by a JSON formatting error.")}})};
|
1150
|
-
this.fnFormatNumber=function(a){if(a<1E3)return a;else{var b=a+"";a=b.split("");var c="";b=b.length;for(var d=0;d<b;d++){if(d%3===0&&d!==0)c=","+c;c=a[b-d-1]+c}}return c};this.aLengthMenu=[
|
1150
|
+
this.fnFormatNumber=function(a){if(a<1E3)return a;else{var b=a+"";a=b.split("");var c="";b=b.length;for(var d=0;d<b;d++){if(d%3===0&&d!==0)c=","+c;c=a[b-d-1]+c}}return c};this.aLengthMenu=[250];this.iDraw=0;this.iDrawError=-1;this._iDisplayLength=250;this._iDisplayStart=0;this._iDisplayEnd=250;this._iRecordsDisplay=this._iRecordsTotal=0;this.bJUI=false;this.oClasses=m.oStdClasses;this.bSorted=this.bFiltered=false;this.oInit=null}function q(a){return function(){var b=[B(this[m.iApiIndex])].concat(Array.prototype.slice.call(arguments));
|
1151
1151
|
return m.oApi[a].apply(this,b)}}function r(a){if(a.bInitialised===false)setTimeout(function(){r(a)},200);else{na(a);z(a);if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();F(a);D(a)}if(a.sAjaxSource!==null&&!a.oFeatures.bServerSide){K(a,true);a.fnServerData.call(a.oInstance,a.sAjaxSource,null,function(b){for(var c=0;c<b.aaData.length;c++)w(a,b.aaData[c]);a.iInitDisplayStart=a._iDisplayStart;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();F(a);D(a)}K(a,false);
|
1152
1152
|
typeof a.fnInitComplete=="function"&&a.fnInitComplete.call(a.oInstance,a,b)})}else{typeof a.fnInitComplete=="function"&&a.fnInitComplete.call(a.oInstance,a);a.oFeatures.bServerSide||K(a,false)}}}function u(a,b,c){n(a.oLanguage,b,"sProcessing");n(a.oLanguage,b,"sLengthMenu");n(a.oLanguage,b,"sEmptyTable");n(a.oLanguage,b,"sZeroRecords");n(a.oLanguage,b,"sInfo");n(a.oLanguage,b,"sInfoEmpty");n(a.oLanguage,b,"sInfoFiltered");n(a.oLanguage,b,"sInfoPostFix");n(a.oLanguage,b,"sSearch");if(typeof b.oPaginate!=
|
1153
1153
|
"undefined"){n(a.oLanguage.oPaginate,b.oPaginate,"sFirst");n(a.oLanguage.oPaginate,b.oPaginate,"sPrevious");n(a.oLanguage.oPaginate,b.oPaginate,"sNext");n(a.oLanguage.oPaginate,b.oPaginate,"sLast")}typeof b.sEmptyTable=="undefined"&&typeof b.sZeroRecords!="undefined"&&n(a.oLanguage,b,"sZeroRecords","sEmptyTable");c&&r(a)}function y(a,b){a.aoColumns[a.aoColumns.length++]={sType:null,_bAutoType:true,bVisible:true,bSearchable:true,bSortable:true,asSorting:["asc","desc"],sSortingClass:a.oClasses.sSortable,
|
data/roadmap.md
CHANGED
@@ -53,4 +53,4 @@ Will be the fully modern release that drops maintenance legacy support in favor
|
|
53
53
|
|
54
54
|
It is important for a project to not only know what problems it is trying to solve, but what things are out of scope. We will start to try to document that here:
|
55
55
|
|
56
|
-
* We have in the past tried to add coverage tracking for all gems, this added a lot of complexity and
|
56
|
+
* We have in the past tried to add coverage tracking for all gems, this added a lot of complexity and computation overhead and slowed things down to much. It also was of less value than we had hoped. There are alternative ways to instrument a shared library to track across multiple applications, and single application gem utilization is easier to handle in a one of basis. It is unlikely we will support that again.
|
@@ -5,7 +5,7 @@ namespace :benchmarks do
|
|
5
5
|
# Enable and start GC before each job run. Disable GC afterwards.
|
6
6
|
#
|
7
7
|
# Inspired by https://www.omniref.com/ruby/2.2.1/symbols/Benchmark/bm?#annotation=4095926&line=182
|
8
|
-
class GCSuite
|
8
|
+
class GCSuite # standard:disable Lint/ConstantDefinitionInBlock
|
9
9
|
def warming(*)
|
10
10
|
run_gc
|
11
11
|
end
|
@@ -99,11 +99,11 @@ namespace :benchmarks do
|
|
99
99
|
Coverband::Collectors::Coverage.instance.reset_instance
|
100
100
|
end
|
101
101
|
|
102
|
-
|
103
|
-
|
102
|
+
lines = 45
|
103
|
+
non_nil_lines = 18
|
104
104
|
def fake_line_numbers
|
105
|
-
|
106
|
-
coverage = line <
|
105
|
+
lines.times.map do |line|
|
106
|
+
coverage = (line < non_nil_lines) ? rand(5) : nil
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
@@ -16,7 +16,7 @@ class AdaptersFileStoreTest < Minitest::Test
|
|
16
16
|
previous_file_path = "#{@test_file_path}.#{::Process.pid}"
|
17
17
|
`rm #{@test_file_path}` if File.exist?(@test_file_path)
|
18
18
|
`rm #{previous_file_path}` if File.exist?(previous_file_path)
|
19
|
-
File.
|
19
|
+
File.write(previous_file_path, test_data.to_json)
|
20
20
|
@store = Coverband::Adapters::FileStore.new(@test_file_path)
|
21
21
|
end
|
22
22
|
|
@@ -53,7 +53,7 @@ class CollectorsCoverageTest < Minitest::Test
|
|
53
53
|
end
|
54
54
|
|
55
55
|
test "defaults to a redis store" do
|
56
|
-
assert_equal Coverband::Adapters::RedisStore, coverband.instance_variable_get(
|
56
|
+
assert_equal Coverband::Adapters::RedisStore, coverband.instance_variable_get(:@store).class
|
57
57
|
end
|
58
58
|
|
59
59
|
test "report_coverage raises errors in tests" do
|
@@ -38,7 +38,7 @@ class ReportJSONTest < Minitest::Test
|
|
38
38
|
json = Coverband::Reporters::JSONReport.new(@store).report
|
39
39
|
parsed = JSON.parse(json)
|
40
40
|
|
41
|
-
expected_keys = ["never_loaded", "runtime_percentage", "lines_of_code", "lines_covered", "lines_missed", "covered_percent", "covered_strength"]
|
41
|
+
expected_keys = ["never_loaded", "runtime_percentage", "lines_of_code", "lines_covered", "lines_runtime", "lines_missed", "covered_percent", "covered_strength"]
|
42
42
|
|
43
43
|
assert_equal parsed["files"].length, 2
|
44
44
|
parsed["files"].keys.each do |file|
|
@@ -7,10 +7,10 @@ require File.expand_path("../../test_helper", File.dirname(__FILE__))
|
|
7
7
|
# initial version of test pulled into Coverband from Simplecov 12/19/2018
|
8
8
|
####
|
9
9
|
describe Coverband::Utils::SourceFile do
|
10
|
-
|
10
|
+
coverage_for_sample_rb = [nil, 1, 1, 1, nil, nil, 1, 0, nil, nil, nil, nil, nil, nil, nil, nil].freeze
|
11
11
|
describe "a source file initialized with some coverage data" do
|
12
12
|
subject do
|
13
|
-
Coverband::Utils::SourceFile.new(source_fixture("sample.rb"),
|
13
|
+
Coverband::Utils::SourceFile.new(source_fixture("sample.rb"), coverage_for_sample_rb)
|
14
14
|
end
|
15
15
|
|
16
16
|
it "has a filename" do
|
@@ -70,7 +70,7 @@ describe Coverband::Utils::SourceFile do
|
|
70
70
|
|
71
71
|
describe "simulating potential Ruby 1.9 defect -- see Issue #56" do
|
72
72
|
subject do
|
73
|
-
Coverband::Utils::SourceFile.new(source_fixture("sample.rb"),
|
73
|
+
Coverband::Utils::SourceFile.new(source_fixture("sample.rb"), coverage_for_sample_rb + [nil])
|
74
74
|
end
|
75
75
|
|
76
76
|
it "has 16 source lines regardless of extra data in coverage array" do
|
@@ -88,10 +88,10 @@ describe Coverband::Utils::SourceFile do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
describe "a file that is never relevant" do
|
91
|
-
|
91
|
+
coverage_for_never_rb = [nil, nil].freeze
|
92
92
|
|
93
93
|
subject do
|
94
|
-
Coverband::Utils::SourceFile.new(source_fixture("never.rb"),
|
94
|
+
Coverband::Utils::SourceFile.new(source_fixture("never.rb"), coverage_for_never_rb)
|
95
95
|
end
|
96
96
|
|
97
97
|
it "has 0.0 covered_strength" do
|
@@ -104,10 +104,10 @@ describe Coverband::Utils::SourceFile do
|
|
104
104
|
end
|
105
105
|
|
106
106
|
describe "a file where nothing is ever executed mixed with skipping #563" do
|
107
|
-
|
107
|
+
coverage_for_skipped_rb = [nil, nil, nil, nil].freeze
|
108
108
|
|
109
109
|
subject do
|
110
|
-
Coverband::Utils::SourceFile.new(source_fixture("skipped.rb"),
|
110
|
+
Coverband::Utils::SourceFile.new(source_fixture("skipped.rb"), coverage_for_skipped_rb)
|
111
111
|
end
|
112
112
|
|
113
113
|
it "has 0.0 covered_strength" do
|
@@ -120,10 +120,10 @@ describe Coverband::Utils::SourceFile do
|
|
120
120
|
end
|
121
121
|
|
122
122
|
describe "a file where everything is skipped and missed #563" do
|
123
|
-
|
123
|
+
coverage_for_skipped_rb_2 = [nil, nil, 0, nil].freeze
|
124
124
|
|
125
125
|
subject do
|
126
|
-
Coverband::Utils::SourceFile.new(source_fixture("skipped.rb"),
|
126
|
+
Coverband::Utils::SourceFile.new(source_fixture("skipped.rb"), coverage_for_skipped_rb_2)
|
127
127
|
end
|
128
128
|
|
129
129
|
it "has 0.0 covered_strength" do
|
@@ -136,10 +136,10 @@ describe Coverband::Utils::SourceFile do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
describe "a file where everything is skipped/irrelevamt but executed #563" do
|
139
|
-
|
139
|
+
coverage_for_skkiped_and_executed_rb = [nil, nil, 1, 1, 0, nil, nil, nil].freeze
|
140
140
|
|
141
141
|
subject do
|
142
|
-
Coverband::Utils::SourceFile.new(source_fixture("skipped_and_executed.rb"),
|
142
|
+
Coverband::Utils::SourceFile.new(source_fixture("skipped_and_executed.rb"), coverage_for_skkiped_and_executed_rb)
|
143
143
|
end
|
144
144
|
|
145
145
|
it "has 0.0 covered_strength" do
|
data/test/fixtures/sample.rb
CHANGED
@@ -11,7 +11,7 @@ class RailsRakeFullStackTest < Minitest::Test
|
|
11
11
|
end
|
12
12
|
|
13
13
|
# test 'rake tasks shows coverage properly within eager_loading' do
|
14
|
-
# this was testing gem data, which we no
|
14
|
+
# this was testing gem data, which we no longer support and I dont know if this makes sense anymre
|
15
15
|
# end
|
16
16
|
|
17
17
|
test "ignored rake tasks don't add coverage" do
|
data/test/test_helper.rb
CHANGED
@@ -92,11 +92,11 @@ Mocha::Configuration.prevent(:stubbing_method_unnecessarily)
|
|
92
92
|
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
93
93
|
|
94
94
|
def test(name, &block)
|
95
|
-
test_name = "test_#{name.gsub(/\s+/, "_")}"
|
95
|
+
test_name = :"test_#{name.gsub(/\s+/, "_")}"
|
96
96
|
defined = begin
|
97
97
|
instance_method(test_name)
|
98
|
-
|
99
|
-
|
98
|
+
rescue
|
99
|
+
false
|
100
100
|
end
|
101
101
|
raise "#{test_name} is already defined in #{self}" if defined
|
102
102
|
|
@@ -172,8 +172,6 @@ ensure
|
|
172
172
|
$stderr = previous_stderr
|
173
173
|
end
|
174
174
|
|
175
|
-
require "coverband"
|
176
|
-
|
177
175
|
Coverband::Configuration.class_eval do
|
178
176
|
def test_env
|
179
177
|
true
|