coco 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|