simplecov-reports 0.0.4.ooyala
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +66 -0
- data/Rakefile +73 -0
- data/lib/simplecov-html-extended.rb +50 -0
- data/lib/simplecov/configuration.rb +98 -0
- data/lib/simplecov/reports.rb +5 -0
- data/lib/simplecov/reports/author_report.rb +180 -0
- data/lib/simplecov/reports/file_report.rb +97 -0
- data/lib/simplecov/reports/version.rb +5 -0
- data/lib/simplecov/source_file.rb +39 -0
- data/simplecov-reports.gemspec +29 -0
- data/test/fixtures/author_report/author_stats_file1.rb +23 -0
- data/test/fixtures/author_report/author_stats_file2.rb +26 -0
- data/test/fixtures/author_report/best_author_tolerance.rb +264 -0
- data/test/fixtures/file_report/classes_covered.rb +80 -0
- data/test/fixtures/file_report/classes_not_covered.rb +37 -0
- data/test/fixtures/file_report/classes_partially_covered.rb +11 -0
- data/test/fixtures/file_report/methods_covered.rb +38 -0
- data/test/fixtures/file_report/methods_not_covered.rb +39 -0
- data/test/fixtures/file_report/methods_partially_covered.rb +13 -0
- data/test/fixtures/line enhancer/line_enhancer_fixture.rb +1 -0
- data/test/helper.rb +19 -0
- data/test/memory_measure.rb +0 -0
- data/test/test_all_reports.rb +35 -0
- data/test/test_author_stats.rb +89 -0
- data/test/test_best_author_stage1.rb +75 -0
- data/test/test_best_author_stage2.rb +75 -0
- data/test/test_best_author_stage3.rb +86 -0
- data/test/test_best_author_stage4.rb +97 -0
- data/test/test_best_author_stage5.rb +97 -0
- data/test/test_file_reports.rb +159 -0
- data/test/test_html_reports.rb +43 -0
- data/test/test_line_enhancer.rb +26 -0
- data/views/author_report.erb +37 -0
- data/views/file_report.erb +21 -0
- metadata +203 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YmU1NzU3NjE3NmZjNGExMTE4MWM2ZWJhOGJhMmNkMjY2Nzk5ZDA3Nw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZWY3ODQ0MjE2MTk2MjBmMzI0NmMzODU3MzFjMjZiZjY0OWE4ZDcyNg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NTQ3ZjdlOTVkNWVlYTc2ZWJiYTRiNzAwMDE2NWIwNzY1NmZjMWJkNmJjOWIz
|
10
|
+
ZmEzOWNlNzI1ZjE5OWMyYjFhYTA4YTQwYzgzMWY5MDFmNWMzODNlNDgwM2Nk
|
11
|
+
ZWQzYjEwZGU3ZDA1Mjk4MmJiZmQ1ZjY4ODYyMzE4ZWExNzc3ODM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzRjODIwZDFmNTMwMzZhYTIzYjQwNDA3NTNlYTg1Y2QzYzRmZjEwMzM3NjZm
|
14
|
+
OGJkNjJhOWQ5ZDg3OTgzMzhlYmFkZTAzMWMxN2Y5ZjcwZTM2NDgzNGFjMGI1
|
15
|
+
YmQ1NzQwZmM3M2E4YjhiZDAyY2Q0OGZhYWNmODBmMTM1N2ZjYmI=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Rajesh Konda
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Simplecov::Reports
|
2
|
+
|
3
|
+
This gem provides author and file analysis based reports to be generated when simplecov generates code
|
4
|
+
coverage reports.
|
5
|
+
|
6
|
+
Author reports include 'best author' and 'author stats'. File analysis based reports include 'api', 'class',
|
7
|
+
'method' and 'configure' coverage reports.
|
8
|
+
|
9
|
+
'api' coverage report gives statistics about the api methods (as specified using Sinatra) that are missing
|
10
|
+
coverage. 'class' coverage report gives statistics about the classes that are missing coverage. 'method'
|
11
|
+
coverage report gives statistics about all the methods/functions that are missing coverage. 'configure'
|
12
|
+
coverage report gives statistics about all the 'configure' blocks (as specified using Sinatra) that are
|
13
|
+
missing coverage.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'simplecov-reports'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install simplecov-reports
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
* require the gem in your .simplecov file
|
32
|
+
|
33
|
+
`require "simplecov/reports"`
|
34
|
+
|
35
|
+
* specify reports you would like to generate, eg.,
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
add_report :type => SimpleCov::Configuration::ReportTypes::ItemsMissingCoverage::Api
|
39
|
+
add_report :type => SimpleCov::Configuration::ReportTypes::ItemsMissingCoverage::Class
|
40
|
+
add_report :type => SimpleCov::Configuration::ReportTypes::ItemsMissingCoverage::Method
|
41
|
+
add_report :type => SimpleCov::Configuration::ReportTypes::ItemsMissingCoverage::Configure
|
42
|
+
add_report(:type => SimpleCov::Configuration::ReportTypes::Author,
|
43
|
+
:sub_types => [
|
44
|
+
SimpleCov::Configuration::ReportTypes::Author::BestAuthor,
|
45
|
+
SimpleCov::Configuration::ReportTypes::Author::AuthorStats
|
46
|
+
],
|
47
|
+
:best_authors_count => 4)
|
48
|
+
```
|
49
|
+
|
50
|
+
### Author reports configuration
|
51
|
+
|
52
|
+
The following options can be passed to the Author report as seen in the example above.
|
53
|
+
|
54
|
+
* `:best-authors-count` : The minimum number of authors to show in the best authors list as long as their coverage satisfies `best-author-cutoff` (default: 3).
|
55
|
+
* `:best-author-tolerance` : Percentage value that limits how authors are selected to show in best authors list. Given m, the most number of lines written by any author, this value v, is the percentage of m, that is a normal cutoff for choosing the best authors. All the authors that have written `v/100 * m` or more lines of code are selected (default: 50.0)
|
56
|
+
* `:best-author-cutoff` : Percentage value that limits how authors are selected to show in best authors list. Given m, the most number of lines written by any author, this value v, is the percentage of m, that is the absolute cutoff for choosing the best authors. All the authors that have written `v/100 * m` or more lines of code are selected, unless the 'best_author_count' is reached (default: 15.0)
|
57
|
+
* `:author-report-from` : Starting date from which authoring is considered, for author stats reports. Format: YYYY-MM-DD HH:MM:SS (-/+)HHMM (default: 1900-12-31 00:00:00 -0000)
|
58
|
+
* `:author-report-to` : Ending date to which authoring is considered, for author stats reports. Format: YYYY-MM-DD HH:MM:SS (-/+)HHMM (default: 2025-12-31 00:00:00 -0000)
|
59
|
+
|
60
|
+
## Contributing
|
61
|
+
|
62
|
+
1. Fork it
|
63
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
64
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
65
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
66
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
|
5
|
+
task :test => [
|
6
|
+
"test_all_reports",
|
7
|
+
"test_best_author",
|
8
|
+
"test_file_reports",
|
9
|
+
"test_html_reports",
|
10
|
+
"test_line_enhancer"
|
11
|
+
]
|
12
|
+
|
13
|
+
Rake::TestTask.new(:test_all_reports) do |test|
|
14
|
+
test.libs << 'lib' << 'test'
|
15
|
+
test.test_files = FileList['test/test_all_reports.rb']
|
16
|
+
test.verbose = true
|
17
|
+
end
|
18
|
+
|
19
|
+
task :test_best_author => [
|
20
|
+
"test_best_author_stage1",
|
21
|
+
"test_best_author_stage2",
|
22
|
+
"test_best_author_stage3",
|
23
|
+
"test_best_author_stage4",
|
24
|
+
"test_best_author_stage5",
|
25
|
+
]
|
26
|
+
|
27
|
+
Rake::TestTask.new(:test_best_author_stage1) do |test|
|
28
|
+
test.libs << 'lib' << 'test'
|
29
|
+
test.test_files = FileList['test/test_best_author_stage1.rb']
|
30
|
+
test.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
Rake::TestTask.new(:test_best_author_stage2) do |test|
|
34
|
+
test.libs << 'lib' << 'test'
|
35
|
+
test.test_files = FileList['test/test_best_author_stage2.rb']
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::TestTask.new(:test_best_author_stage3) do |test|
|
40
|
+
test.libs << 'lib' << 'test'
|
41
|
+
test.test_files = FileList['test/test_best_author_stage3.rb']
|
42
|
+
test.verbose = true
|
43
|
+
end
|
44
|
+
|
45
|
+
Rake::TestTask.new(:test_best_author_stage4) do |test|
|
46
|
+
test.libs << 'lib' << 'test'
|
47
|
+
test.test_files = FileList['test/test_best_author_stage4.rb']
|
48
|
+
test.verbose = true
|
49
|
+
end
|
50
|
+
|
51
|
+
Rake::TestTask.new(:test_best_author_stage5) do |test|
|
52
|
+
test.libs << 'lib' << 'test'
|
53
|
+
test.test_files = FileList['test/test_best_author_stage5.rb']
|
54
|
+
test.verbose = true
|
55
|
+
end
|
56
|
+
|
57
|
+
Rake::TestTask.new(:test_file_reports) do |test|
|
58
|
+
test.libs << 'lib' << 'test'
|
59
|
+
test.test_files = FileList['test/test_file_reports.rb']
|
60
|
+
test.verbose = true
|
61
|
+
end
|
62
|
+
|
63
|
+
Rake::TestTask.new(:test_html_reports) do |test|
|
64
|
+
test.libs << 'lib' << 'test'
|
65
|
+
test.test_files = FileList['test/test_html_reports.rb']
|
66
|
+
test.verbose = true
|
67
|
+
end
|
68
|
+
|
69
|
+
Rake::TestTask.new(:test_line_enhancer) do |test|
|
70
|
+
test.libs << 'lib' << 'test'
|
71
|
+
test.test_files = FileList['test/test_line_enhancer.rb']
|
72
|
+
test.verbose = true
|
73
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "simplecov-html"
|
2
|
+
|
3
|
+
|
4
|
+
module SimpleCov
|
5
|
+
module Formatter
|
6
|
+
class HTMLFormatter
|
7
|
+
def formatted_file_report(report)
|
8
|
+
case report[:type][:subtype]
|
9
|
+
when :api
|
10
|
+
when :class
|
11
|
+
when :method
|
12
|
+
when :configure
|
13
|
+
end
|
14
|
+
title = "#{report[:type]} #{report[:type][:subtype]}"
|
15
|
+
title_id = title.gsub(/^[^a-zA-Z]+/, '').gsub(/[^a-zA-Z0-9\-\_]/, '')
|
16
|
+
template('file_report').result(binding)
|
17
|
+
end
|
18
|
+
|
19
|
+
def formatted_author_report(report)
|
20
|
+
generated_source = ""
|
21
|
+
report[:sub_reports].each do |sub_report|
|
22
|
+
case sub_report[:type]
|
23
|
+
when :best_authors
|
24
|
+
when :author_stats
|
25
|
+
end
|
26
|
+
title = "#{report[:type]} #{sub_report[:type]}"
|
27
|
+
title_id = title.gsub(/^[^a-zA-Z]+/, '').gsub(/[^a-zA-Z0-9\-\_]/, '')
|
28
|
+
generated_source += template('author_report').result(binding)
|
29
|
+
end
|
30
|
+
generated_source
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Add report formatters
|
35
|
+
formatters = {
|
36
|
+
:file_report => :formatted_file_report,
|
37
|
+
:author_report => :formatted_author_report
|
38
|
+
}
|
39
|
+
|
40
|
+
HTMLFormatter.add_report_formatters(formatters)
|
41
|
+
|
42
|
+
# Author report would like to add author information to the source file view
|
43
|
+
HTMLFormatter::Views::SourceFile.add_line_attribute "author", lambda { |line| line.author }
|
44
|
+
HTMLFormatter::Views::SourceFile.add_line_attribute "authored_date", lambda { |line| line.date }
|
45
|
+
|
46
|
+
# Add the "views" directory in this gem as a path to finding erb files
|
47
|
+
gem_root = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
48
|
+
HTMLFormatter.erb_files.append_path(File.join(gem_root, "views"))
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
#
|
2
|
+
# Enhancements to SimpleCov::Configuration for generating reports
|
3
|
+
#
|
4
|
+
require "simplecov"
|
5
|
+
|
6
|
+
module SimpleCov::Configuration
|
7
|
+
|
8
|
+
module ReportTypes
|
9
|
+
module ItemsMissingCoverage
|
10
|
+
module Api
|
11
|
+
def self.get_specification(options)
|
12
|
+
{ :type => :file_report,
|
13
|
+
:options => {
|
14
|
+
:report_type => :api
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Class
|
21
|
+
def self.get_specification(options)
|
22
|
+
{ :type => :file_report,
|
23
|
+
:options => {
|
24
|
+
:report_type => :class
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Method
|
31
|
+
def self.get_specification(options)
|
32
|
+
{ :type => :file_report,
|
33
|
+
:options => {
|
34
|
+
:report_type => :method
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module Configure
|
41
|
+
def self.get_specification(options)
|
42
|
+
{ :type => :file_report,
|
43
|
+
:options => {
|
44
|
+
:report_type => :configure
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # module ItemsMissingCoverage
|
50
|
+
|
51
|
+
module Author
|
52
|
+
def self.get_specification(options)
|
53
|
+
specification =
|
54
|
+
{ :type => :author_report,
|
55
|
+
:options => {
|
56
|
+
:report_types => {},
|
57
|
+
:best_authors_count =>
|
58
|
+
options.has_key?(:best_authors_count) ? options[:best_authors_count] : 3,
|
59
|
+
|
60
|
+
:best_author_tolerance =>
|
61
|
+
options.has_key?(:best_author_tolerance) ? options[:best_author_tolerance] : 50.00,
|
62
|
+
|
63
|
+
:best_author_cutoff =>
|
64
|
+
options.has_key?(:best_author_cutoff) ? options[:best_author_cutoff] : 15.00,
|
65
|
+
|
66
|
+
:author_report_from =>
|
67
|
+
options.has_key?(:author_report_from) ? options[:author_report_from] : "1900-12-31 00:00:00 -0000",
|
68
|
+
|
69
|
+
:author_report_to =>
|
70
|
+
options.has_key?(:author_report_to) ? options[:author_report_to] : "2025-12-31 00:00:00 -0000"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
options[:sub_types].each do |author_type|
|
75
|
+
specification = author_type.get_specification(options, specification)
|
76
|
+
end
|
77
|
+
specification
|
78
|
+
end
|
79
|
+
|
80
|
+
module BestAuthor
|
81
|
+
def self.get_specification(options, specification)
|
82
|
+
specification[:options][:report_types][:best_authors] = true
|
83
|
+
specification
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
module AuthorStats
|
88
|
+
def self.get_specification(options, specification)
|
89
|
+
specification[:options][:report_types][:author_stats] = true
|
90
|
+
specification
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end # module Author
|
94
|
+
|
95
|
+
end # module ReportTypes
|
96
|
+
|
97
|
+
end # module SimpleCov::Configuration
|
98
|
+
|
@@ -0,0 +1,180 @@
|
|
1
|
+
#
|
2
|
+
# AuthorReport gives statistics on coverage mapped to the authors of the code.
|
3
|
+
#
|
4
|
+
|
5
|
+
require "algorithms"
|
6
|
+
require "simplecov"
|
7
|
+
require_relative "../source_file"
|
8
|
+
|
9
|
+
module SimpleCov
|
10
|
+
class AuthorReport < Report
|
11
|
+
attr_reader :author_stats_mapping, :best_author_stats_mapping
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@options = options
|
15
|
+
@report_types = options[:report_types]
|
16
|
+
|
17
|
+
# For each author, there is a mapping to a file/linesOfCode map
|
18
|
+
# 'file/linesOfCode map': mapping from file name to the stats about coverage for code
|
19
|
+
@author_stats_mapping = {}
|
20
|
+
@best_author_stats_mapping = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate(files)
|
24
|
+
compute_author_stats_mapping(files)
|
25
|
+
if @report_types[:best_authors]
|
26
|
+
compute_best_authors
|
27
|
+
end
|
28
|
+
|
29
|
+
@report = {
|
30
|
+
:type => {
|
31
|
+
:main => :author_report,
|
32
|
+
},
|
33
|
+
:sub_reports => []
|
34
|
+
}
|
35
|
+
|
36
|
+
if @report_types[:best_authors]
|
37
|
+
@report[:sub_reports] <<
|
38
|
+
{
|
39
|
+
:type => :best_authors,
|
40
|
+
:title => "Best Authors",
|
41
|
+
:items => @best_author_stats_mapping
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
if @report_types[:author_stats]
|
46
|
+
@report[:sub_reports] <<
|
47
|
+
{
|
48
|
+
:type => :author_stats,
|
49
|
+
:title => "Author Stats",
|
50
|
+
:items => @author_stats_mapping
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
@report
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def compute_author_stats_mapping(files)
|
59
|
+
files.each do |file|
|
60
|
+
file.lines.each do |line|
|
61
|
+
next if line.author.nil? || line.date.nil?
|
62
|
+
next if(line.date < Time.parse(@options[:author_report_from]) ||
|
63
|
+
line.date > Time.parse(@options[:author_report_to]))
|
64
|
+
|
65
|
+
@author_stats_mapping[line.author] = @author_stats_mapping[line.author] || {}
|
66
|
+
files_stats = @author_stats_mapping[line.author][:files] =
|
67
|
+
@author_stats_mapping[line.author][:files] || ItemMap.new
|
68
|
+
files_stats[file] =
|
69
|
+
files_stats[file] || {}
|
70
|
+
|
71
|
+
if line.missed?
|
72
|
+
files_stats[file][:missed] =
|
73
|
+
files_stats[file][:missed] || 0
|
74
|
+
files_stats[file][:missed] += 1
|
75
|
+
elsif line.covered?
|
76
|
+
files_stats[file][:covered] =
|
77
|
+
files_stats[file][:covered] || 0
|
78
|
+
files_stats[file][:covered] += 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
@author_stats_mapping.keys.each do |author_name|
|
83
|
+
files_stats = @author_stats_mapping[author_name][:files]
|
84
|
+
next if files_stats[file].nil?
|
85
|
+
files_stats[file][:covered] =
|
86
|
+
files_stats[file][:covered] || 0
|
87
|
+
files_stats[file][:missed] =
|
88
|
+
files_stats[file][:missed] || 0
|
89
|
+
|
90
|
+
if files_stats[file][:covered] == 0 &&
|
91
|
+
files_stats[file][:missed] == 0
|
92
|
+
files_stats.delete(file)
|
93
|
+
next
|
94
|
+
end
|
95
|
+
|
96
|
+
files_stats[file][:total] =
|
97
|
+
files_stats[file][:covered] +
|
98
|
+
files_stats[file][:missed]
|
99
|
+
files_stats[file][:coverage] =
|
100
|
+
compute_coverage(files_stats[file])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
@author_stats_mapping.keys.each do |author_name|
|
105
|
+
total_lines = 0
|
106
|
+
total_covered_lines = 0
|
107
|
+
|
108
|
+
author_stats = @author_stats_mapping[author_name]
|
109
|
+
author_stats[:files].keys.each do |file|
|
110
|
+
total_lines += author_stats[:files][file][:missed] +
|
111
|
+
author_stats[:files][file][:covered]
|
112
|
+
total_covered_lines += author_stats[:files][file][:covered]
|
113
|
+
end
|
114
|
+
author_stats[:total_coverage] = {}
|
115
|
+
author_stats[:total_coverage][:missed] = total_lines - total_covered_lines
|
116
|
+
author_stats[:total_coverage][:covered] = total_covered_lines
|
117
|
+
author_stats[:total_coverage][:total] =
|
118
|
+
author_stats[:total_coverage][:missed] +
|
119
|
+
author_stats[:total_coverage][:covered]
|
120
|
+
author_stats[:total_coverage][:coverage] =
|
121
|
+
compute_coverage(author_stats[:total_coverage])
|
122
|
+
end
|
123
|
+
|
124
|
+
@author_stats_mapping
|
125
|
+
end # compute_author_stats_mapping
|
126
|
+
|
127
|
+
def compute_coverage(file_stats)
|
128
|
+
return 0 if file_stats[:total] == 0
|
129
|
+
100 * file_stats[:covered].to_f / file_stats[:total]
|
130
|
+
end
|
131
|
+
|
132
|
+
def compute_best_authors
|
133
|
+
all_authors_queue = Containers::PriorityQueue.new
|
134
|
+
significant_authors_queue = Containers::PriorityQueue.new
|
135
|
+
|
136
|
+
@author_stats_mapping.keys.each do |author_name|
|
137
|
+
author_stats = @author_stats_mapping[author_name]
|
138
|
+
all_authors_queue.push(author_name, author_stats[:total_coverage][:total])
|
139
|
+
end
|
140
|
+
|
141
|
+
most_total_author = all_authors_queue.pop
|
142
|
+
return if most_total_author.nil?
|
143
|
+
significant_authors_queue.push(most_total_author,
|
144
|
+
@author_stats_mapping[most_total_author][:total_coverage][:coverage])
|
145
|
+
author_count = 1
|
146
|
+
while(author_name = all_authors_queue.pop) != nil &&
|
147
|
+
(
|
148
|
+
comparable( @author_stats_mapping[most_total_author][:total_coverage][:total],
|
149
|
+
@author_stats_mapping[author_name][:total_coverage][:total]) ||
|
150
|
+
(
|
151
|
+
comparable_cutoff( @author_stats_mapping[most_total_author][:total_coverage][:total],
|
152
|
+
@author_stats_mapping[author_name][:total_coverage][:total]) &&
|
153
|
+
author_count < @options[:best_authors_count]
|
154
|
+
)
|
155
|
+
)
|
156
|
+
significant_authors_queue.push(author_name,
|
157
|
+
@author_stats_mapping[author_name][:total_coverage][:coverage])
|
158
|
+
author_count += 1
|
159
|
+
end
|
160
|
+
|
161
|
+
author_count = 0
|
162
|
+
while (author_name = significant_authors_queue.pop) != nil
|
163
|
+
@best_author_stats_mapping[author_name] = @author_stats_mapping[author_name]
|
164
|
+
author_count += 1
|
165
|
+
end
|
166
|
+
end # compute_best_authors
|
167
|
+
|
168
|
+
def comparable(baseline, candidate)
|
169
|
+
candidate.to_f / baseline * 100 >= @options[:best_author_tolerance]
|
170
|
+
end
|
171
|
+
|
172
|
+
def comparable_cutoff(baseline, candidate)
|
173
|
+
candidate.to_f / baseline * 100 >= @options[:best_author_cutoff]
|
174
|
+
end
|
175
|
+
|
176
|
+
end # class AuthorReport
|
177
|
+
|
178
|
+
end # module SimpleCov
|
179
|
+
|
180
|
+
SimpleCov::Report.register(:author_report, SimpleCov::AuthorReport)
|