coco 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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/TODO ADDED
@@ -0,0 +1,3 @@
1
+
2
+ * rubygem
3
+ * quick web site (on GitHub ?)
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,4 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'coco/cover/coverage_stat'
4
+ require 'coco/cover/coverage_result'
@@ -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