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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTORS +9 -0
  3. data/Changelog.markdown +42 -0
  4. data/Gemfile.lock +36 -55
  5. data/LICENSE +7 -0
  6. data/README.markdown +124 -73
  7. data/Rakefile +10 -37
  8. data/VERSION +1 -1
  9. data/lib/coco.rb +9 -21
  10. data/lib/coco/configuration.rb +59 -20
  11. data/lib/coco/cover.rb +1 -0
  12. data/lib/coco/cover/coverage_result.rb +72 -16
  13. data/lib/coco/cover/coverage_stat.rb +20 -8
  14. data/lib/coco/cover/summary.rb +50 -0
  15. data/lib/coco/deprecated_message.rb +31 -0
  16. data/lib/coco/formatter.rb +2 -2
  17. data/lib/coco/formatter/colored_string.rb +1 -1
  18. data/lib/coco/formatter/console_formatter.rb +24 -19
  19. data/lib/coco/formatter/context.rb +10 -39
  20. data/lib/coco/formatter/html_formatter.rb +7 -13
  21. data/lib/coco/formatter/html_index_formatter.rb +20 -16
  22. data/lib/coco/formatter/index_context.rb +37 -0
  23. data/lib/coco/formatter/index_line.rb +21 -0
  24. data/lib/coco/formatter/template.rb +2 -3
  25. data/lib/coco/helpers.rb +88 -68
  26. data/lib/coco/lister/source_lister.rb +23 -26
  27. data/lib/coco/lister/uncovered_lister.rb +6 -9
  28. data/lib/coco/project.rb +65 -0
  29. data/lib/coco/theme.rb +15 -0
  30. data/lib/coco/writer/file_writer.rb +5 -5
  31. data/lib/coco/writer/html_directory.rb +16 -8
  32. data/lib/coco/writer/html_files_writer.rb +9 -6
  33. data/lib/coco/writer/html_index_writer.rb +6 -3
  34. data/template/css/dark.css +178 -0
  35. data/template/css/{coco.css → light.css} +22 -9
  36. data/template/file.erb +3 -3
  37. data/template/index.erb +35 -33
  38. data/template/js/coco.js +18 -0
  39. metadata +34 -58
  40. data/COPYING +0 -674
  41. data/lib/coco/formatter/formatter.rb +0 -23
  42. data/template/img/coconut16.png +0 -0
  43. 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
@@ -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'
@@ -7,7 +7,7 @@ module Coco
7
7
  # Public: Initialize a new ColoredString object.
8
8
  #
9
9
  # str - A String.
10
- def initialize(str="")
10
+ def initialize(str = '')
11
11
  super(str)
12
12
  end
13
13
 
@@ -1,24 +1,25 @@
1
1
  module Coco
2
2
 
3
3
  # I format coverages data for console output.
4
- class ConsoleFormatter < Formatter
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
- def format(single_line_report = false)
13
- single_line_report ? single_line_message : @formatted_output.join("\n")
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
- "See file://" +
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
- # covered - See base class Formatter.
30
- # uncovered - See base class Formatter.
30
+ # uncovered - An Array list of uncovered files.
31
31
  # threshold - The Fixnum percentage threshold.
32
- def initialize(covered, uncovered, threshold)
33
- super(covered, uncovered)
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
- @raw_coverages.each do |filename, coverage|
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
- if @uncovered.empty?
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
- # Returns Binding.
19
- def get_binding
20
- binding
21
- end
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
- def get_binding
51
- binding
52
- end
53
- end
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 coverages information into html files.
7
- # @todo document and change name to HtmlFilesFormatter
8
- class HtmlFormatter < Formatter
6
+ # I format coverage's data into html files.
7
+ #
8
+ class HtmlFormatter
9
9
 
10
10
  def initialize(raw_coverages)
11
- super(raw_coverages, [])
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
- source(filename).each_with_index do |line, index|
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.get_binding)
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
- class HtmlIndexFormatter < Formatter
7
-
8
- def initialize(raw_coverages, uncovered)
9
- super
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
- Helpers.index_title,
19
- @lines,
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
- @raw_coverages.each do |filename, coverage|
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
- ERB.new(io[0], nil, '><')
12
+ ERB.new(io[0], nil, '><')
13
13
  end
14
14
  end
15
-
16
15
  end
@@ -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
- # Public: Get a String (ruby) source filename ready to be
11
- # displayed in the index file.
12
- #
13
- # name - String full path filename (normaly full path but, who
14
- # knows? may be relative path).
15
- #
16
- # Examples
17
- #
18
- # name = '/home/user/my_project/lib/source.rb'
19
- # Helpers.name_for_html(name)
20
- # #=> 'lib/<b>source.rb</b>'
21
- #
22
- # Returns the formatted String.
23
- def name_for_html(name)
24
- name = File.expand_path(name)
25
- name = name.sub(Dir.pwd, '')
26
- name = name.sub(/^\//, '')
27
- base = File.basename(name)
28
- name.sub(base, "<b>#{base}</b>")
29
- end
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
- # Public: Get html filename (from a ruby filename) suitable for
32
- # the coverage directory.
33
- #
34
- # name - String full path filename.
35
- #
36
- # Examples
37
- #
38
- # ruby = '/home/user/my_project/lib/source.rb'
39
- # html = Helpers.rb2html(ruby)
40
- # #=> '_lib_source.rb.html'
41
- #
42
- # Returns String HTML filename.
43
- def rb2html(name)
44
- name = name.sub(Dir.pwd, '')
45
- name = name.sub(/^\//, '')
46
- name = name.tr('/\\', '_')
47
- name + '.html'
48
- end
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
- # Public: Get page title for the index.html file.
51
- #
52
- # Returns String.
53
- def 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
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
- # 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
- def expand(files)
65
- files.map {|file| File.expand_path(file) }
66
- end
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
- # Public: Get all ruby files from a directory, including
69
- # sub-directories.
70
- #
71
- # directory - String directory to look into.
72
- #
73
- # Returns an Array of String.
74
- def rb_files_from(directory)
75
- rb_files = File.join(directory, "**", "*.rb")
76
- Dir.glob(rb_files)
77
- end
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