coco 0.4.1
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.
- data/COPYING +674 -0
- data/NEWS +34 -0
- data/README.rdoc +48 -0
- data/Rakefile +32 -0
- data/TODO +3 -0
- data/VERSION +1 -0
- data/lib/coco.rb +33 -0
- data/lib/coco/configuration.rb +35 -0
- data/lib/coco/cover.rb +4 -0
- data/lib/coco/cover/coverage_result.rb +48 -0
- data/lib/coco/cover/coverage_stat.rb +33 -0
- data/lib/coco/formatter.rb +9 -0
- data/lib/coco/formatter/colored_string.rb +33 -0
- data/lib/coco/formatter/console_formatter.rb +46 -0
- data/lib/coco/formatter/context.rb +35 -0
- data/lib/coco/formatter/formatter.rb +22 -0
- data/lib/coco/formatter/html_formatter.rb +39 -0
- data/lib/coco/formatter/html_index_formatter.rb +37 -0
- data/lib/coco/formatter/template.rb +17 -0
- data/lib/coco/helpers.rb +36 -0
- data/lib/coco/lister.rb +4 -0
- data/lib/coco/lister/source_lister.rb +47 -0
- data/lib/coco/lister/uncovered_lister.rb +26 -0
- data/lib/coco/writer.rb +6 -0
- data/lib/coco/writer/file_writer.rb +14 -0
- data/lib/coco/writer/html_directory.rb +39 -0
- data/lib/coco/writer/html_files_writer.rb +32 -0
- data/lib/coco/writer/html_index_writer.rb +21 -0
- data/template/css/LICENCE +5 -0
- data/template/css/base-min.css +1 -0
- data/template/css/coco.css +96 -0
- data/template/css/ext.css +5 -0
- data/template/css/fonts-min.css +1 -0
- data/template/css/reset-min.css +1 -0
- data/template/file.erb +35 -0
- data/template/img/coconut16.png +0 -0
- data/template/img/licenses +19 -0
- data/template/index.erb +58 -0
- metadata +113 -0
data/NEWS
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
v0.4.1 (2011-02-27)
|
2
|
+
|
3
|
+
* Quick fix, add forgotten images for html menu
|
4
|
+
|
5
|
+
|
6
|
+
v0.4 (2011-02-26)
|
7
|
+
|
8
|
+
* add colors to console output (*nix only)
|
9
|
+
|
10
|
+
* it can exclude unwanted files from the report
|
11
|
+
|
12
|
+
|
13
|
+
v0.3 (2011-02-25)
|
14
|
+
|
15
|
+
* Report sources not covered at all
|
16
|
+
|
17
|
+
* Configurable via a simple yaml file
|
18
|
+
+ threeshold
|
19
|
+
+ source directories
|
20
|
+
|
21
|
+
* UTF-8 compliant
|
22
|
+
|
23
|
+
* Misc
|
24
|
+
+ sort index.html and console output by percentage
|
25
|
+
+ display coco's version in index.html
|
26
|
+
|
27
|
+
|
28
|
+
v0.2 (2011-02-24)
|
29
|
+
|
30
|
+
* Use coco from rspec with a simple require 'coco'
|
31
|
+
|
32
|
+
* Display filenames covered < 90% on console
|
33
|
+
|
34
|
+
* Build simple html report only for files covered < 90%
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= coco
|
2
|
+
|
3
|
+
Another COde COverage for ruby 1.9 (from the famous post of Aaron Patterson).
|
4
|
+
This one suits my needs.
|
5
|
+
|
6
|
+
== Features
|
7
|
+
* Use it from rspec with a simple <code>require 'coco'</code>
|
8
|
+
* Display filenames covered < 90% on console
|
9
|
+
* Build <em>simple</em> html report <em>only</em> for files covered < 90%
|
10
|
+
* Report sources that have no tests
|
11
|
+
* UTF-8 compliant
|
12
|
+
* Configuration could be done via a simple yaml file
|
13
|
+
* Colorized console output (*nix only)
|
14
|
+
|
15
|
+
<em>Note: I have tested coco only on debian linux. I have not tested it with the test/unit
|
16
|
+
framework.</em>
|
17
|
+
|
18
|
+
== Documentation
|
19
|
+
|
20
|
+
require 'coco'
|
21
|
+
|
22
|
+
at the beginning of your tests, usually in a \*helper\*.rb file.
|
23
|
+
|
24
|
+
See {the wiki}[https://github.com/lkdjiin/coco/wiki] for more information on using coco.
|
25
|
+
|
26
|
+
To generate the developper's documentation in YARD format:
|
27
|
+
rake doc
|
28
|
+
|
29
|
+
== Dependencies
|
30
|
+
|
31
|
+
ruby >= 1.9.2
|
32
|
+
|
33
|
+
To contribute:
|
34
|
+
|
35
|
+
* reek
|
36
|
+
* rspec
|
37
|
+
|
38
|
+
== Installing coco
|
39
|
+
Download and
|
40
|
+
rake install
|
41
|
+
|
42
|
+
== License
|
43
|
+
GPLv3, see COPYING.
|
44
|
+
|
45
|
+
== Questions and/or Comments
|
46
|
+
|
47
|
+
Feel free to email {Xavier Nayrac}[mailto:xavier.nayrac@gmail.com]
|
48
|
+
with any questions.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
desc 'Test coco'
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
desc 'Test coco'
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
11
|
+
t.rspec_opts = ['--color']
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Check for code smells'
|
15
|
+
task :reek do
|
16
|
+
puts 'Checking for code smells...'
|
17
|
+
files = Dir.glob 'lib/**/*.rb'
|
18
|
+
args = files.join(' ')
|
19
|
+
sh "reek --quiet #{args} | ./reek.sed"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Build the gem & install it'
|
23
|
+
task :install do
|
24
|
+
sh "gem build coco.gemspec"
|
25
|
+
f = FileList['coco*gem'].to_a
|
26
|
+
sh "gem install #{f.first} --no-rdoc --no-ri"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Generate yard documentation for developpers'
|
30
|
+
task :doc do
|
31
|
+
exec 'yardoc --title "Coco Documentation" - NEWS COPYING VERSION'
|
32
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.1
|
data/lib/coco.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
4
|
+
$COCO_PATH = File.expand_path(File.expand_path(File.dirname(__FILE__)) + '/..')
|
5
|
+
require 'coco/formatter'
|
6
|
+
require 'coco/cover'
|
7
|
+
require 'coco/writer'
|
8
|
+
require 'coco/helpers'
|
9
|
+
require 'coco/configuration'
|
10
|
+
require 'coco/lister'
|
11
|
+
require 'coverage'
|
12
|
+
|
13
|
+
module Coco
|
14
|
+
end
|
15
|
+
|
16
|
+
Coverage.start
|
17
|
+
|
18
|
+
at_exit do
|
19
|
+
config = Coco::Configuration.new
|
20
|
+
result = Coco::CoverageResult.new(config, Coverage.result)
|
21
|
+
covered = result.covered_from_domain
|
22
|
+
|
23
|
+
sources = Coco::SourceLister.new(config).list
|
24
|
+
uncovered = Coco::UncoveredLister.new(sources, result.all_from_domain).list
|
25
|
+
|
26
|
+
puts Coco::ConsoleFormatter.new(covered, uncovered).format
|
27
|
+
|
28
|
+
html_files = Coco::HtmlFormatter.new(covered).format
|
29
|
+
Coco::HtmlFilesWriter.new(html_files).write
|
30
|
+
|
31
|
+
index = Coco::HtmlIndexFormatter.new(covered, uncovered).format
|
32
|
+
Coco::HtmlIndexWriter.new(index).write
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Coco
|
6
|
+
|
7
|
+
# I know the configuration of coco.
|
8
|
+
#
|
9
|
+
# @example read the threeshold value
|
10
|
+
# config = Configuration.new
|
11
|
+
# config[:threeshold]
|
12
|
+
# => 90
|
13
|
+
#
|
14
|
+
# You can override the default configuration by putting a '.coco' file
|
15
|
+
# in YAML format in the project root directory.
|
16
|
+
# @example to override the threeshold put this line in a '.coco' file:
|
17
|
+
# :threeshold: 70
|
18
|
+
#
|
19
|
+
# @note You can set the threeshold above 100% (to be sure to see all files) but you
|
20
|
+
# cannot set it under 0.
|
21
|
+
class Configuration < Hash
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
self[:threeshold] = 90
|
25
|
+
self[:directories] = ['lib']
|
26
|
+
self[:excludes] = []
|
27
|
+
if File.exist?('.coco')
|
28
|
+
conf = YAML.load_file '.coco'
|
29
|
+
self.merge!(conf)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/coco/cover.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# Compute results of interest from the big results information (from Coverage.result)
|
6
|
+
class CoverageResult
|
7
|
+
# @return [Hash] Coverage for all the sources that live in the root project folder.
|
8
|
+
attr_reader :all_from_domain
|
9
|
+
# @return [Hash] Coverage for sources that are not sufficiently covered.
|
10
|
+
# More technically, the sources that live in the root project folder and for
|
11
|
+
# which the coverage percentage is under the threeshold.
|
12
|
+
attr_reader :covered_from_domain
|
13
|
+
|
14
|
+
# @param [Hash] config
|
15
|
+
# @param [Hash] raw_results Results obtained from Coverage.result
|
16
|
+
def initialize config, raw_results
|
17
|
+
@exclude_files = config[:excludes]
|
18
|
+
@threeshold = config[:threeshold]
|
19
|
+
raise ArgumentError if @threeshold < 0
|
20
|
+
@result = raw_results
|
21
|
+
exclude_external_sources
|
22
|
+
exclude_files_user_dont_want
|
23
|
+
exclude_sources_above_threeshold
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def exclude_external_sources
|
29
|
+
here = Dir.pwd
|
30
|
+
@all_from_domain = @result.select {|key, value| key.start_with? here}
|
31
|
+
end
|
32
|
+
|
33
|
+
def exclude_files_user_dont_want
|
34
|
+
return if @exclude_files.nil?
|
35
|
+
@exclude_files.each do |filename|
|
36
|
+
@all_from_domain.delete(File.expand_path(filename))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def exclude_sources_above_threeshold
|
41
|
+
@covered_from_domain = @all_from_domain.select {|key, value|
|
42
|
+
CoverageStat.coverage_percent(value) < @threeshold
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# Give statistics about an array of lines hit.
|
6
|
+
#
|
7
|
+
# An "array of lines hit" is an array of integers, possibly nil.
|
8
|
+
# Such array is obtain from Coverage.result.
|
9
|
+
#
|
10
|
+
# Each integer represent the state of a source line:
|
11
|
+
# * nil: source line will never be reached (like comments)
|
12
|
+
# * 0: source line could be reached, but was not
|
13
|
+
# * 1 and above: number of time the source line has been reached
|
14
|
+
class CoverageStat
|
15
|
+
|
16
|
+
def CoverageStat.remove_nil_from hits
|
17
|
+
hits.select {|elem| not elem.nil?}
|
18
|
+
end
|
19
|
+
|
20
|
+
def CoverageStat.number_of_covered_lines hits
|
21
|
+
hits.select {|elem| elem > 0}.size
|
22
|
+
end
|
23
|
+
|
24
|
+
def CoverageStat.coverage_percent hits
|
25
|
+
hits = CoverageStat.remove_nil_from hits
|
26
|
+
return 0 if hits.empty?
|
27
|
+
one_percent = 100.0 / hits.size
|
28
|
+
(CoverageStat.number_of_covered_lines(hits) * one_percent).to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'coco/formatter/formatter'
|
2
|
+
|
3
|
+
require 'coco/formatter/console_formatter'
|
4
|
+
require 'coco/formatter/context'
|
5
|
+
|
6
|
+
require 'coco/formatter/html_formatter'
|
7
|
+
require 'coco/formatter/html_index_formatter'
|
8
|
+
require 'coco/formatter/template'
|
9
|
+
require 'coco/formatter/colored_string'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# Extend String with ANSI colorization.
|
6
|
+
# Do nothing on Windows.
|
7
|
+
class ColoredString < String
|
8
|
+
|
9
|
+
def initialize(str="")
|
10
|
+
super(str)
|
11
|
+
end
|
12
|
+
|
13
|
+
def red
|
14
|
+
colorize "\033[31m"
|
15
|
+
end
|
16
|
+
|
17
|
+
def yellow
|
18
|
+
colorize "\033[33m"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def colorize color_code
|
24
|
+
if RUBY_PLATFORM =~ /win32/
|
25
|
+
self
|
26
|
+
else
|
27
|
+
"#{color_code}#{self}\033[0m"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# I format coverages information for console output
|
6
|
+
class ConsoleFormatter < Formatter
|
7
|
+
|
8
|
+
# return [string] percent covered and associated filenames
|
9
|
+
def format
|
10
|
+
@formatted_output.join("\n")
|
11
|
+
end
|
12
|
+
|
13
|
+
# @param [Hash] covered
|
14
|
+
# @param [Array] uncovered
|
15
|
+
def initialize covered, uncovered
|
16
|
+
super(covered, uncovered)
|
17
|
+
@formatted_output = []
|
18
|
+
compute_percentage
|
19
|
+
add_percentage_to_uncovered
|
20
|
+
@formatted_output.sort!
|
21
|
+
@formatted_output.map! do |percentage, filename|
|
22
|
+
text = ColoredString.new "#{percentage}% #{filename}"
|
23
|
+
if percentage <= 50
|
24
|
+
text.red
|
25
|
+
else
|
26
|
+
text.yellow
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def compute_percentage
|
34
|
+
@raw_coverages.each do |filename, coverage|
|
35
|
+
percentage = CoverageStat.coverage_percent(coverage)
|
36
|
+
@formatted_output << [percentage, filename]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_percentage_to_uncovered
|
41
|
+
@uncovered.each do |filename| @formatted_output << [0, filename] end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# Contextual information for ERB template, representing each covered files.
|
6
|
+
class Context
|
7
|
+
|
8
|
+
# @param [String] filename Name of the source file
|
9
|
+
# @param [Array] lines
|
10
|
+
def initialize filename, lines
|
11
|
+
@filename = filename
|
12
|
+
@lines = lines
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_binding
|
16
|
+
binding
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Contextual information for ERB template, representing index.html.
|
21
|
+
class IndexContext
|
22
|
+
|
23
|
+
# @todo doc, inheritance (with Context)
|
24
|
+
def initialize title, covered, uncovered
|
25
|
+
@title = title
|
26
|
+
@covered = covered
|
27
|
+
@uncovered = uncovered
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_binding
|
31
|
+
binding
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# My childs will format coverages information.
|
6
|
+
# @abstract
|
7
|
+
class Formatter
|
8
|
+
|
9
|
+
# @param [Hash] raw_coverages The hash from Coverage.result
|
10
|
+
# @param [Array] uncovered List on uncovered files
|
11
|
+
# @todo I think covered is a better name than raw_coverages
|
12
|
+
def initialize raw_coverages, uncovered
|
13
|
+
@raw_coverages = raw_coverages
|
14
|
+
@uncovered = uncovered
|
15
|
+
end
|
16
|
+
|
17
|
+
def format
|
18
|
+
"Implement me in child"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Coco
|
6
|
+
|
7
|
+
# I format coverages information into html files.
|
8
|
+
# @todo document and change name to HtmlFilesFormatter
|
9
|
+
class HtmlFormatter < Formatter
|
10
|
+
|
11
|
+
def initialize raw_coverages
|
12
|
+
super(raw_coverages, [])
|
13
|
+
@formatted_output_files = {}
|
14
|
+
@context = nil
|
15
|
+
@template = Template.open File.join($COCO_PATH,'template/file.erb')
|
16
|
+
end
|
17
|
+
|
18
|
+
def format
|
19
|
+
@raw_coverages.each do |filename, coverage|
|
20
|
+
build_html filename, coverage
|
21
|
+
end
|
22
|
+
@formatted_output_files
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def build_html filename, coverage
|
28
|
+
source = File.readlines filename
|
29
|
+
lines = []
|
30
|
+
source.each_with_index do |line, index|
|
31
|
+
lines << [index+1, line.chomp, coverage[index]]
|
32
|
+
end
|
33
|
+
@context = Context.new filename, lines
|
34
|
+
@formatted_output_files[filename] = @template.result(@context.get_binding)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|