coco 0.13.0 → 0.14.0
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.
- checksums.yaml +4 -4
- data/CONTRIBUTORS +9 -0
- data/Changelog.markdown +42 -0
- data/Gemfile.lock +36 -55
- data/LICENSE +7 -0
- data/README.markdown +124 -73
- data/Rakefile +10 -37
- data/VERSION +1 -1
- data/lib/coco.rb +9 -21
- data/lib/coco/configuration.rb +59 -20
- data/lib/coco/cover.rb +1 -0
- data/lib/coco/cover/coverage_result.rb +72 -16
- data/lib/coco/cover/coverage_stat.rb +20 -8
- data/lib/coco/cover/summary.rb +50 -0
- data/lib/coco/deprecated_message.rb +31 -0
- data/lib/coco/formatter.rb +2 -2
- data/lib/coco/formatter/colored_string.rb +1 -1
- data/lib/coco/formatter/console_formatter.rb +24 -19
- data/lib/coco/formatter/context.rb +10 -39
- data/lib/coco/formatter/html_formatter.rb +7 -13
- data/lib/coco/formatter/html_index_formatter.rb +20 -16
- data/lib/coco/formatter/index_context.rb +37 -0
- data/lib/coco/formatter/index_line.rb +21 -0
- data/lib/coco/formatter/template.rb +2 -3
- data/lib/coco/helpers.rb +88 -68
- data/lib/coco/lister/source_lister.rb +23 -26
- data/lib/coco/lister/uncovered_lister.rb +6 -9
- data/lib/coco/project.rb +65 -0
- data/lib/coco/theme.rb +15 -0
- data/lib/coco/writer/file_writer.rb +5 -5
- data/lib/coco/writer/html_directory.rb +16 -8
- data/lib/coco/writer/html_files_writer.rb +9 -6
- data/lib/coco/writer/html_index_writer.rb +6 -3
- data/template/css/dark.css +178 -0
- data/template/css/{coco.css → light.css} +22 -9
- data/template/file.erb +3 -3
- data/template/index.erb +35 -33
- data/template/js/coco.js +18 -0
- metadata +34 -58
- data/COPYING +0 -674
- data/lib/coco/formatter/formatter.rb +0 -23
- data/template/img/coconut16.png +0 -0
- data/template/img/licenses +0 -19
@@ -0,0 +1,31 @@
|
|
1
|
+
module Coco
|
2
|
+
|
3
|
+
# Group all messages for deprecated things in this module.
|
4
|
+
#
|
5
|
+
module DeprecatedMessage
|
6
|
+
|
7
|
+
def self.for_excludes
|
8
|
+
"Please change `excludes` to `exclude`.\n" \
|
9
|
+
'Support for `excludes` configuration key will ' \
|
10
|
+
'be removed in future Coco versions.'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.for_directories
|
14
|
+
"Please change `directories` to `include`.\n" \
|
15
|
+
'Support for `directories` configuration key will ' \
|
16
|
+
'be removed in future Coco versions.'
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.for_threeshold
|
20
|
+
"Please change `threeshold` to `threshold`.\n" \
|
21
|
+
'Support for the misspelt `threeshold` configuration key will ' \
|
22
|
+
'be removed in future Coco versions.'
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.for_legacy_config_file
|
26
|
+
"Please use `.coco.yml` instead of `.coco`.\n" \
|
27
|
+
'Support for `.coco` will be removed in future versions.'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/coco/formatter.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'coco/formatter/formatter'
|
2
|
-
|
3
1
|
require 'coco/formatter/console_formatter'
|
4
2
|
require 'coco/formatter/context'
|
3
|
+
require 'coco/formatter/index_context'
|
5
4
|
|
6
5
|
require 'coco/formatter/html_formatter'
|
7
6
|
require 'coco/formatter/html_index_formatter'
|
8
7
|
require 'coco/formatter/template'
|
9
8
|
require 'coco/formatter/colored_string'
|
9
|
+
require 'coco/formatter/index_line'
|
@@ -1,24 +1,25 @@
|
|
1
1
|
module Coco
|
2
2
|
|
3
3
|
# I format coverages data for console output.
|
4
|
-
|
4
|
+
#
|
5
|
+
class ConsoleFormatter
|
5
6
|
|
6
7
|
# Public: Get a colored report, formatted for console output.
|
7
8
|
#
|
8
|
-
# single_line_report - Boolean
|
9
|
-
#
|
10
9
|
# Returns percent covered and associated filenames as a multilines
|
11
|
-
# String
|
12
|
-
|
13
|
-
|
10
|
+
# or a single line String.
|
11
|
+
#
|
12
|
+
def format
|
13
|
+
@config[:single_line_report] ? single_line_message : multilines_message
|
14
14
|
end
|
15
15
|
|
16
16
|
# Get the link for the report's index file.
|
17
17
|
#
|
18
18
|
# Returns String.
|
19
|
+
#
|
19
20
|
def link
|
20
21
|
unless @formatted_output.empty?
|
21
|
-
|
22
|
+
'See file://' +
|
22
23
|
File.expand_path(File.join(Coco::HtmlDirectory.new.coverage_dir,
|
23
24
|
'index.html'))
|
24
25
|
end
|
@@ -26,11 +27,15 @@ module Coco
|
|
26
27
|
|
27
28
|
# Public: Creates a new ConsoleFormatter.
|
28
29
|
#
|
29
|
-
#
|
30
|
-
# uncovered - See base class Formatter.
|
30
|
+
# uncovered - An Array list of uncovered files.
|
31
31
|
# threshold - The Fixnum percentage threshold.
|
32
|
-
|
33
|
-
|
32
|
+
# result - A CoverageResult.
|
33
|
+
# config - A Configuration.
|
34
|
+
#
|
35
|
+
def initialize(uncovered, threshold, result, config)
|
36
|
+
@uncovered = uncovered
|
37
|
+
@result = result
|
38
|
+
|
34
39
|
@formatted_output = []
|
35
40
|
compute_percentage
|
36
41
|
add_percentage_to_uncovered
|
@@ -45,29 +50,29 @@ module Coco
|
|
45
50
|
text.yellow
|
46
51
|
end
|
47
52
|
end
|
53
|
+
@summary = Summary.new(result, uncovered)
|
54
|
+
@config = config
|
48
55
|
end
|
49
56
|
|
50
57
|
private
|
51
58
|
|
52
59
|
def compute_percentage
|
53
|
-
@
|
60
|
+
@result.not_covered_enough.each do |filename, coverage|
|
54
61
|
percentage = CoverageStat.coverage_percent(coverage)
|
55
62
|
@formatted_output << [percentage, filename]
|
56
63
|
end
|
57
64
|
end
|
58
65
|
|
59
66
|
def add_percentage_to_uncovered
|
60
|
-
@uncovered.each {|filename| @formatted_output << [0, filename] }
|
67
|
+
@uncovered.each { |filename| @formatted_output << [0, filename] }
|
61
68
|
end
|
62
69
|
|
63
70
|
def single_line_message
|
64
|
-
|
65
|
-
""
|
66
|
-
else
|
67
|
-
ColoredString.new("Some files are uncovered").yellow
|
68
|
-
end
|
71
|
+
ColoredString.new(@summary.to_s).yellow
|
69
72
|
end
|
70
73
|
|
74
|
+
def multilines_message
|
75
|
+
@formatted_output.join("\n") + "\n" + @summary.to_s + "\n"
|
76
|
+
end
|
71
77
|
end
|
72
|
-
|
73
78
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Coco
|
2
2
|
|
3
3
|
# Contextual information for ERB template, representing each covered files.
|
4
|
+
#
|
4
5
|
class Context
|
5
6
|
|
6
7
|
# Public: Initialize a Context for a covered file shown in the HTML
|
@@ -8,48 +9,18 @@ module Coco
|
|
8
9
|
#
|
9
10
|
# filename - A String name of the source file.
|
10
11
|
# lines - An Array of lines.
|
11
|
-
def initialize(filename, lines)
|
12
|
-
@filename = filename
|
13
|
-
@lines = lines
|
14
|
-
end
|
15
|
-
|
16
|
-
# Public: Get the object's binding.
|
17
12
|
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
# Contextual information for ERB template, representing index.html.
|
25
|
-
class IndexContext
|
13
|
+
def initialize(filename, lines)
|
14
|
+
@filename = filename
|
15
|
+
@lines = lines
|
16
|
+
end
|
26
17
|
|
27
|
-
# Public: Initialize an IndexContext for the index file in the HTML
|
28
|
-
# report.
|
29
|
-
#
|
30
|
-
# title - The String title for the report.
|
31
|
-
# covered - Array of subarrays. Each subarray is:
|
32
|
-
# [
|
33
|
-
# Fixnum coverage percentage,
|
34
|
-
# String formatted filename (HTML ready),
|
35
|
-
# String real filename
|
36
|
-
# ]
|
37
|
-
# FIXME Need a class to handle subarrays.
|
38
|
-
# uncovered - Array of String filenames. The filenames are already
|
39
|
-
# formatted, ready to be display in an HTML file.
|
40
|
-
#
|
41
|
-
def initialize(title, covered, uncovered)
|
42
|
-
@title = title
|
43
|
-
@covered = covered
|
44
|
-
@uncovered = uncovered
|
45
|
-
end
|
46
|
-
|
47
18
|
# Public: Get the object's binding.
|
48
19
|
#
|
49
20
|
# Returns Binding.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
21
|
+
#
|
22
|
+
def variables
|
23
|
+
binding
|
24
|
+
end
|
25
|
+
end
|
55
26
|
end
|
@@ -3,12 +3,12 @@ require 'erb'
|
|
3
3
|
|
4
4
|
module Coco
|
5
5
|
|
6
|
-
# I format
|
7
|
-
#
|
8
|
-
class HtmlFormatter
|
6
|
+
# I format coverage's data into html files.
|
7
|
+
#
|
8
|
+
class HtmlFormatter
|
9
9
|
|
10
10
|
def initialize(raw_coverages)
|
11
|
-
|
11
|
+
@raw_coverages = raw_coverages
|
12
12
|
@formatted_output_files = {}
|
13
13
|
@context = nil
|
14
14
|
@template = Template.open(File.join(Coco::ROOT, 'template/file.erb'))
|
@@ -25,17 +25,11 @@ module Coco
|
|
25
25
|
|
26
26
|
def build_html(filename, coverage)
|
27
27
|
lines = []
|
28
|
-
|
29
|
-
lines << [index+1, CGI.escapeHTML(line.chomp), coverage[index]]
|
28
|
+
File.readlines(filename).each_with_index do |line, index|
|
29
|
+
lines << [index + 1, CGI.escapeHTML(line.chomp), coverage[index]]
|
30
30
|
end
|
31
31
|
@context = Context.new(Helpers.name_for_html(filename), lines)
|
32
|
-
@formatted_output_files[filename] = @template.result(@context.
|
32
|
+
@formatted_output_files[filename] = @template.result(@context.variables)
|
33
33
|
end
|
34
|
-
|
35
|
-
def source(filename)
|
36
|
-
File.readlines(filename)
|
37
|
-
end
|
38
|
-
|
39
34
|
end
|
40
|
-
|
41
35
|
end
|
@@ -3,10 +3,18 @@ require 'erb'
|
|
3
3
|
module Coco
|
4
4
|
|
5
5
|
# I format the index.html
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
#
|
7
|
+
class HtmlIndexFormatter
|
8
|
+
|
9
|
+
# uncovered - An Array list of uncovered files.
|
10
|
+
# result - CoverageResult.
|
11
|
+
# threshold - Fixnum.
|
12
|
+
#
|
13
|
+
def initialize(uncovered, result, threshold = 100)
|
14
|
+
@uncovered = uncovered
|
15
|
+
@result = result
|
16
|
+
@threshold = threshold
|
17
|
+
@summary = Summary.new(result, uncovered)
|
10
18
|
@context = nil
|
11
19
|
@template = Template.open(File.join(Coco::ROOT, 'template/index.erb'))
|
12
20
|
@lines = []
|
@@ -14,26 +22,22 @@ module Coco
|
|
14
22
|
end
|
15
23
|
|
16
24
|
def format
|
17
|
-
@context = IndexContext.new(
|
18
|
-
|
19
|
-
|
20
|
-
@uncovered.map {|filename| Helpers.name_for_html(filename) })
|
21
|
-
@template.result(@context.get_binding)
|
25
|
+
@context = IndexContext.new(Helpers.index_title, @lines, uncovered_files,
|
26
|
+
@summary, @threshold)
|
27
|
+
@template.result(@context.variables)
|
22
28
|
end
|
23
29
|
|
24
30
|
private
|
25
31
|
|
26
32
|
def build_lines_for_context
|
27
|
-
@
|
28
|
-
@lines <<
|
29
|
-
CoverageStat.coverage_percent(coverage),
|
30
|
-
Helpers.name_for_html(filename),
|
31
|
-
Helpers.rb2html(filename)
|
32
|
-
]
|
33
|
+
@result.coverable_files.to_a.each do |filename, coverage|
|
34
|
+
@lines << IndexLine.build(filename, coverage)
|
33
35
|
end
|
34
36
|
@lines.sort!
|
35
37
|
end
|
36
38
|
|
39
|
+
def uncovered_files
|
40
|
+
@uncovered.map { |filename| Helpers.name_for_html(filename) }
|
41
|
+
end
|
37
42
|
end
|
38
|
-
|
39
43
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Coco
|
2
|
+
|
3
|
+
# Contextual information for ERB template, representing index.html.
|
4
|
+
#
|
5
|
+
class IndexContext
|
6
|
+
|
7
|
+
# Public: Initialize an IndexContext for the index file in the HTML
|
8
|
+
# report.
|
9
|
+
#
|
10
|
+
# title - The String title for the report.
|
11
|
+
# all - Array of subarrays. Each subarray is:
|
12
|
+
# [
|
13
|
+
# Fixnum coverage percentage,
|
14
|
+
# String formatted filename (HTML ready),
|
15
|
+
# String real filename
|
16
|
+
# ]
|
17
|
+
# uncovered - Array of String filenames. The filenames are already
|
18
|
+
# formatted, ready to be display in an HTML file.
|
19
|
+
# summary - A Summary object.
|
20
|
+
# threshold - Fixnum.
|
21
|
+
#
|
22
|
+
def initialize(title, all, uncovered, summary, threshold)
|
23
|
+
@title = title
|
24
|
+
@covered, @greens = all.partition { |file| file.first < threshold }
|
25
|
+
@uncovered = uncovered
|
26
|
+
@summary = summary
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Get the object's binding.
|
30
|
+
#
|
31
|
+
# Returns Binding.
|
32
|
+
#
|
33
|
+
def variables
|
34
|
+
binding
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Coco
|
2
|
+
|
3
|
+
# Assembles data required to represent a line on the index HTML
|
4
|
+
# report.
|
5
|
+
#
|
6
|
+
module IndexLine
|
7
|
+
|
8
|
+
# filename - The absolute String filename.
|
9
|
+
# coverage - An Array of hit.
|
10
|
+
#
|
11
|
+
# Returns an Array.
|
12
|
+
#
|
13
|
+
def self.build(filename, coverage)
|
14
|
+
[
|
15
|
+
CoverageStat.coverage_percent(coverage),
|
16
|
+
Helpers.name_for_html(filename),
|
17
|
+
Helpers.rb2html(filename),
|
18
|
+
]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'erb'
|
2
2
|
|
3
3
|
module Coco
|
4
|
-
|
4
|
+
|
5
5
|
# From me, you can obtain ERB templates.
|
6
6
|
class Template
|
7
7
|
# filename - An String ERB template.
|
@@ -9,8 +9,7 @@ module Coco
|
|
9
9
|
# Returns ERB.
|
10
10
|
def self.open(filename)
|
11
11
|
io = IO.readlines(filename, nil)
|
12
|
-
|
12
|
+
ERB.new(io[0], nil, '><')
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
16
15
|
end
|
data/lib/coco/helpers.rb
CHANGED
@@ -2,81 +2,101 @@ module Coco
|
|
2
2
|
|
3
3
|
# Public: Collection of application's helpers methods.
|
4
4
|
#
|
5
|
-
# TODO The app is full of `Dir.pwd`. This is the root project
|
6
|
-
# directory and must be in Configuration class (or Coco module ?).
|
7
5
|
module Helpers
|
8
|
-
class << self
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
7
|
+
# Public: Get a String (ruby) source filename ready to be
|
8
|
+
# displayed in the index file.
|
9
|
+
#
|
10
|
+
# name - String full path filename (normaly full path but, who
|
11
|
+
# knows? may be relative path).
|
12
|
+
#
|
13
|
+
# Examples
|
14
|
+
#
|
15
|
+
# name = '/home/user/my_project/lib/source.rb'
|
16
|
+
# Helpers.name_for_html(name)
|
17
|
+
# #=> 'lib/<b>source.rb</b>'
|
18
|
+
#
|
19
|
+
# Returns the formatted String.
|
20
|
+
#
|
21
|
+
def self.name_for_html(name)
|
22
|
+
name = File.expand_path(name)
|
23
|
+
name = name.sub(Dir.pwd, '')
|
24
|
+
name = name.sub(%r{^/}, '')
|
25
|
+
base = File.basename(name)
|
26
|
+
name.sub(base, "<b>#{base}</b>")
|
27
|
+
end
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
29
|
+
# Public: Get html filename (from a ruby filename) suitable for
|
30
|
+
# the coverage directory.
|
31
|
+
#
|
32
|
+
# name - String full path filename.
|
33
|
+
#
|
34
|
+
# Examples
|
35
|
+
#
|
36
|
+
# ruby = '/home/user/my_project/lib/source.rb'
|
37
|
+
# html = Helpers.rb2html(ruby)
|
38
|
+
# #=> '_lib_source.rb.html'
|
39
|
+
#
|
40
|
+
# Returns String HTML filename.
|
41
|
+
#
|
42
|
+
def self.rb2html(name)
|
43
|
+
name = name.sub(Dir.pwd, '')
|
44
|
+
name = name.sub(%r{^/}, '')
|
45
|
+
name = name.tr('/\\', '_')
|
46
|
+
name + '.html'
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
# Public: Get page title for the index.html file.
|
50
|
+
#
|
51
|
+
# Returns String.
|
52
|
+
#
|
53
|
+
def self.index_title
|
54
|
+
project_name = File.basename(Dir.pwd)
|
55
|
+
version = File.read(File.join(Coco::ROOT, 'VERSION')).strip
|
56
|
+
"#{project_name} - Code coverage (coco #{version})"
|
57
|
+
end
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
# Public: Expands a bulk of filenames into full path filenames.
|
60
|
+
#
|
61
|
+
# files - List of filenames as an Array of String.
|
62
|
+
#
|
63
|
+
# Returns an Array of String.
|
64
|
+
#
|
65
|
+
def self.expand(files)
|
66
|
+
files.map { |file| File.expand_path(file) }
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
# Public: Get all ruby files from a directory, including
|
70
|
+
# sub-directories.
|
71
|
+
#
|
72
|
+
# directory - String directory to look into.
|
73
|
+
#
|
74
|
+
# Returns an Array of String.
|
75
|
+
#
|
76
|
+
def self.rb_files_from(directory)
|
77
|
+
rb_files = File.join(directory, '**', '*.rb')
|
78
|
+
Dir.glob(rb_files)
|
78
79
|
end
|
79
80
|
|
81
|
+
# Public: Get the CSS class given a percentage. To use in the
|
82
|
+
# index file.
|
83
|
+
#
|
84
|
+
# percentage - A Fixnum.
|
85
|
+
#
|
86
|
+
# Examples
|
87
|
+
#
|
88
|
+
# Helpers.level_class(100)
|
89
|
+
# #=> 'green'
|
90
|
+
#
|
91
|
+
# Returns the String CSS class name.
|
92
|
+
#
|
93
|
+
def self.level_class(percentage)
|
94
|
+
case percentage
|
95
|
+
when 100 then 'green'
|
96
|
+
when 80..99 then 'yellow'
|
97
|
+
else
|
98
|
+
'red'
|
99
|
+
end
|
100
|
+
end
|
80
101
|
end
|
81
|
-
|
82
102
|
end
|