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
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Coco
|
6
|
+
|
7
|
+
# I format the index.html
|
8
|
+
# @todo document
|
9
|
+
class HtmlIndexFormatter < Formatter
|
10
|
+
|
11
|
+
def initialize raw_coverages, uncovered
|
12
|
+
super(raw_coverages, uncovered)
|
13
|
+
@context = nil
|
14
|
+
@template = Template.open File.join($COCO_PATH,'template/index.erb')
|
15
|
+
@lines = []
|
16
|
+
build_lines_for_context
|
17
|
+
end
|
18
|
+
|
19
|
+
def format
|
20
|
+
@context = IndexContext.new Helpers.index_title, @lines, @uncovered
|
21
|
+
@template.result(@context.get_binding)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def build_lines_for_context
|
27
|
+
@raw_coverages.each do |filename, coverage|
|
28
|
+
filename = File.expand_path(filename)
|
29
|
+
percentage = CoverageStat.coverage_percent(coverage)
|
30
|
+
@lines << [percentage, filename, Helpers.rb2html(filename)]
|
31
|
+
end
|
32
|
+
@lines.sort!
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Coco
|
6
|
+
|
7
|
+
# From me, you can obtain ERB templates.
|
8
|
+
class Template
|
9
|
+
# @param [String] filename An ERB template
|
10
|
+
# @return [ERB]
|
11
|
+
def self.open filename
|
12
|
+
io = IO.readlines(filename, nil)
|
13
|
+
ERB.new(io[0], nil, '><')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/coco/helpers.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# @todo The app is full of <tt>Dir.pwd</tt>. This is the root project directory
|
6
|
+
# and must be in Configuration class (or Coco module ?).
|
7
|
+
module Helpers
|
8
|
+
|
9
|
+
# Get html filename (from a ruby filename) suitable for the coverage
|
10
|
+
# directory.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# ruby = '/home/user/my_project/lib/source.rb'
|
14
|
+
# html = Helpers.rb2html(ruby)
|
15
|
+
# => '_lib_source.rb.html'
|
16
|
+
#
|
17
|
+
# @param [String] name Ruby filename
|
18
|
+
# @return [String] Html filename
|
19
|
+
def Helpers.rb2html name
|
20
|
+
name.sub(Dir.pwd, '').tr('/\\', '_') + '.html'
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [String] The title of the index.html file
|
24
|
+
def Helpers.index_title
|
25
|
+
"Coco #{File.read(File.join($COCO_PATH, 'VERSION')).strip}, code coverage for #{File.basename(Dir.pwd)}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [Array<String>] files List of filenames
|
29
|
+
# @return [Array<String>]
|
30
|
+
def Helpers.expand files
|
31
|
+
files.map {|file| File.expand_path file}
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/coco/lister.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# I retrieve the .rb files from a list of directories.
|
6
|
+
class SourceLister
|
7
|
+
|
8
|
+
# @param [Hash] config
|
9
|
+
def initialize config
|
10
|
+
@exclude_files = config[:excludes]
|
11
|
+
dirs = config[:directories]
|
12
|
+
unless dirs.is_a? Array
|
13
|
+
@folders = [dirs]
|
14
|
+
else
|
15
|
+
@folders = dirs
|
16
|
+
end
|
17
|
+
@folders.each {|folder| raise ArgumentError unless File.directory?(folder)}
|
18
|
+
@list = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Array<String>] A list of all .rb files from the directories found in configuration
|
22
|
+
def list
|
23
|
+
look_for_sources
|
24
|
+
@list.map! {|file| File.expand_path(file)}
|
25
|
+
exclude_files_user_dont_want
|
26
|
+
@list
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def look_for_sources
|
32
|
+
@folders.each do |folder|
|
33
|
+
rb_files = File.join(folder, "**", "*.rb")
|
34
|
+
@list += Dir.glob(rb_files)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def exclude_files_user_dont_want
|
39
|
+
return if @exclude_files.nil?
|
40
|
+
@exclude_files.each do |filename|
|
41
|
+
@list.delete File.expand_path(filename)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# I retrieve the list of uncovered (0%) .rb files.
|
6
|
+
class UncoveredLister
|
7
|
+
|
8
|
+
# @param [Array<String>] sources List of filenames
|
9
|
+
# @param [Hash] covered Raw coverage from the domain
|
10
|
+
def initialize sources, covered
|
11
|
+
@source_files = Helpers.expand(sources)
|
12
|
+
@covered_files = Helpers.expand(covered.keys)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Array<String>] List of uncovered filenames
|
16
|
+
def list
|
17
|
+
list = []
|
18
|
+
@source_files.each do |elem|
|
19
|
+
list << elem unless @covered_files.include?(elem)
|
20
|
+
end
|
21
|
+
list
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/lib/coco/writer.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# I prepare the coverage/ directory for html files.
|
6
|
+
class HtmlDirectory
|
7
|
+
attr_reader :coverage_dir
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@coverage_dir = 'coverage'
|
11
|
+
@css_dir = 'coverage/css'
|
12
|
+
@img_dir = 'coverage/img'
|
13
|
+
css = File.join($COCO_PATH, 'template/css')
|
14
|
+
@css_files = Dir.glob(css + '/*')
|
15
|
+
img = File.join($COCO_PATH, 'template/img')
|
16
|
+
@img_files = Dir.glob(img + '/*')
|
17
|
+
end
|
18
|
+
|
19
|
+
# Delete the coverage/ directory
|
20
|
+
def clean
|
21
|
+
FileUtils.remove_dir @coverage_dir if File.exist? @coverage_dir
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup
|
25
|
+
FileUtils.makedirs @css_dir
|
26
|
+
FileUtils.makedirs @img_dir
|
27
|
+
FileUtils.cp @css_files, @css_dir
|
28
|
+
FileUtils.cp @img_files, @img_dir
|
29
|
+
end
|
30
|
+
|
31
|
+
# I list the html files from the coverage directory
|
32
|
+
def list
|
33
|
+
files = Dir.glob("#{@coverage_dir}/*.html")
|
34
|
+
files.map {|file| File.basename(file)}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# I populate the coverage/ directory with files, if any.
|
6
|
+
class HtmlFilesWriter
|
7
|
+
|
8
|
+
# @param [Hash] html_files Key is filename, value is html content
|
9
|
+
def initialize html_files
|
10
|
+
@html_files = html_files
|
11
|
+
@html_dir = HtmlDirectory.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def write
|
15
|
+
@html_dir.clean
|
16
|
+
if @html_files.size > 0
|
17
|
+
@html_dir.setup
|
18
|
+
write_each_file
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def write_each_file
|
25
|
+
@html_files.each do |filename, html|
|
26
|
+
FileWriter.write File.join('coverage', Helpers.rb2html(filename)), html
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Coco
|
4
|
+
|
5
|
+
# I write the index.html
|
6
|
+
class HtmlIndexWriter
|
7
|
+
|
8
|
+
def initialize index
|
9
|
+
@index = index
|
10
|
+
@dir = HtmlDirectory.new.coverage_dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def write
|
14
|
+
if File.exist?(@dir)
|
15
|
+
FileWriter.write File.join(@dir, 'index.html'), @index
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}
|
@@ -0,0 +1,96 @@
|
|
1
|
+
@charset "UTF-8";
|
2
|
+
@import url("reset-min.css");
|
3
|
+
@import url("base-min.css");
|
4
|
+
@import url("font-min.css");
|
5
|
+
@import url("ext.css");
|
6
|
+
|
7
|
+
html
|
8
|
+
{
|
9
|
+
background-color: #fcfcff;
|
10
|
+
}
|
11
|
+
|
12
|
+
h2
|
13
|
+
{
|
14
|
+
padding: 10px;
|
15
|
+
background-color: #668;
|
16
|
+
color: #fcfcff;
|
17
|
+
}
|
18
|
+
|
19
|
+
a
|
20
|
+
{
|
21
|
+
color:#446;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
p.menu a
|
26
|
+
{
|
27
|
+
font-weight: bold;
|
28
|
+
}
|
29
|
+
|
30
|
+
p.license
|
31
|
+
{
|
32
|
+
color: #888;
|
33
|
+
margin-top: 20px;
|
34
|
+
padding-top: 5px;
|
35
|
+
border-top: 1px solid #888;
|
36
|
+
font-size: 80%;
|
37
|
+
}
|
38
|
+
|
39
|
+
p.date
|
40
|
+
{
|
41
|
+
font-size: 80%;
|
42
|
+
}
|
43
|
+
|
44
|
+
table td
|
45
|
+
{
|
46
|
+
border-width: 0;
|
47
|
+
}
|
48
|
+
|
49
|
+
table.source td
|
50
|
+
{
|
51
|
+
padding: 0;
|
52
|
+
}
|
53
|
+
|
54
|
+
tr.never
|
55
|
+
{
|
56
|
+
background-color: #eee;
|
57
|
+
}
|
58
|
+
|
59
|
+
tr.hit
|
60
|
+
{
|
61
|
+
background-color: #efe;
|
62
|
+
}
|
63
|
+
|
64
|
+
tr.miss
|
65
|
+
{
|
66
|
+
background-color: #fbb;
|
67
|
+
}
|
68
|
+
|
69
|
+
td.yellow
|
70
|
+
{
|
71
|
+
background-color: #fffead;
|
72
|
+
}
|
73
|
+
|
74
|
+
td.orange
|
75
|
+
{
|
76
|
+
background-color: #ffcd84;
|
77
|
+
}
|
78
|
+
|
79
|
+
td.pink
|
80
|
+
{
|
81
|
+
background-color: #ffcd84;
|
82
|
+
}
|
83
|
+
|
84
|
+
td.red
|
85
|
+
{
|
86
|
+
background-color: #ff4747;
|
87
|
+
color: #fff;
|
88
|
+
font-weight: bold;
|
89
|
+
}
|
90
|
+
|
91
|
+
td.black
|
92
|
+
{
|
93
|
+
background-color: #002;
|
94
|
+
color: #fff;
|
95
|
+
font-weight: bold;
|
96
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
|
@@ -0,0 +1 @@
|
|
1
|
+
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
|
data/template/file.erb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta charset='utf-8'>
|
4
|
+
<title><%= @filename %></title>
|
5
|
+
<link rel="stylesheet" href="css/coco.css" type="text/css" />
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<p class="menu">
|
9
|
+
<a href="index.html">Index</a> <img src="img/coconut16.png" width="16" height="16" />
|
10
|
+
<a href="https://github.com/lkdjiin/coco/wiki">Wiki</a> <img src="img/coconut16.png" width="16" height="16" />
|
11
|
+
<a href="https://github.com/lkdjiin/coco">Source</a> <img src="img/coconut16.png" width="16" height="16" />
|
12
|
+
<a href="#">Web site</a>
|
13
|
+
</p>
|
14
|
+
<h2><%= @filename %></h2>
|
15
|
+
<p class="date"><%= "#{Time.now}" %></p>
|
16
|
+
|
17
|
+
<table class="source">
|
18
|
+
|
19
|
+
<% @lines.each do |num, text, hit|%>
|
20
|
+
<% if hit.nil? %>
|
21
|
+
<tr class="never">
|
22
|
+
<% elsif hit.zero? %>
|
23
|
+
<tr class="miss">
|
24
|
+
<% elsif hit > 0 %>
|
25
|
+
<tr class="hit" %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<%= "<td><pre>#{num} </pre></td><td><pre>#{text}</pre></td>" %>
|
29
|
+
|
30
|
+
</tr>
|
31
|
+
<% end%>
|
32
|
+
|
33
|
+
</table>
|
34
|
+
</body>
|
35
|
+
</html>
|